﻿/*
 * @Description: Dynamics Online 公共库封装
 * @Author: 魏威
 * @Date: 2020-10-15 10:55:59
 * @LastEditTime: 2020-11-11 11:54:13
 */

/*global console */
/*global window */
/*global Xrm */

var DynaHx = (function () {
    "use strict";
    var Log = (function () {

        /**
         * 记录操作日志
         * @param {string} message 操作信息
         * @param {string} operationname 操作名称
         * @param {number} loglevel 日志级别  
         * @param {object} optionParames 可选参数
         * @param {string} optionParames.operationpage 操作页面
         * @param {boolean} optionParames.successed 是否成功
         * @param {Date} optionParames.operationdate 操作时间
         */
        var writeInfo = function (message, operationname, loglevel, optionParames) {
            var asyncFunc = function () {
                var loggerEnableVal = Bus.getConfigValue("KEY_LoggerEnable");
                var isEnableActionLog = true;
                if (!Core.Type.isNullOrEmpty(loggerEnableVal)) {
                    var loggerEnable = JSON.parse(loggerEnableVal);
                    isEnableActionLog = Core.Type.isBoolean(loggerEnable.IsEnableActionLog) ? loggerEnable.IsEnableActionLog : isEnableActionLog;
                }

                if (isEnableActionLog) {
                    var entity = {};
                    entity["mcs_operationname"] = !Core.Type.isNullOrEmpty(operationname) ? operationname : "";;
                    entity["mcs_loglevel"] = Core.Type.isNumber(loglevel) ? loglevel : "";
                    entity["mcs_message"] = !Core.Type.isNullOrEmpty(message) ? message : "";

                    optionParames = Core.Type.isObject(optionParames) ? optionParames : {};
                    entity["mcs_operationpage"] = !Core.Type.isNullOrEmpty(optionParames.operationpage) ? optionParames.operationpage : "";
                    entity["mcs_successed"] = Core.Type.isBoolean(optionParames.successed) ? optionParames.successed : true;

                    if (Core.Type.isDate(optionParames.operationdate)) {
                        entity["mcs_operationdate"] = optionParames.operationdate;
                    }

                    Da.createRecord("mcs_operationlog", entity, {
                        successCallback: optionParames.successCallback,
                        errorCallback: optionParames.errorCallback,
                    });
                }
            }
            window.setTimeout(asyncFunc, 0);
        };

        /**
         * 记录错误日志
         * @param {string} message 错误信息
         * @param {object} optionParames 可选参数
         * @param {string} optionParames.ipaddress IP地址
         * @param {string} optionParames.servername 服务器名称
         * @param {string} optionParames.modulename 模块名称
         * @param {string} optionParames.applicationname 系统日志
         * @param {Date} optionParames.exceptiontime 操作时间
         * @param {Date} optionParames.queuedtime 操作时间
         * @param {Date} optionParames.dequeuedtime 操作时间
         */
        var writeErr = function (message, optionParames) {
            var asyncFunc = function () {

                var loggerEnableVal = Bus.getConfigValue("KEY_LoggerEnable");
                var isEnableErrorLog = true;
                if (!Core.Type.isNullOrEmpty(loggerEnableVal)) {
                    var loggerEnable = JSON.parse(loggerEnableVal);
                    isEnableErrorLog = Core.Type.isBoolean(loggerEnable.IsEnableErrorLog) ? loggerEnable.IsEnableErrorLog : isEnableErrorLog;
                }
                if (isEnableErrorLog) {
                    var entity = {};
                    entity["mcs_message"] = !Core.Type.isNullOrEmpty(message) ? message : "";
                    optionParames = Core.Type.isObject(optionParames) ? optionParames : {};
                    entity["mcs_ipaddress"] = !Core.Type.isNullOrEmpty(optionParames.ipaddress) ? optionParames.ipaddress : "";
                    entity["mcs_servername"] = !Core.Type.isNullOrEmpty(optionParames.servername) ? optionParames.servername : "";
                    entity["mcs_applicationname"] = !Core.Type.isNullOrEmpty(optionParames.applicationname) ? optionParames.applicationname : "";
                    entity["mcs_modulename"] = !Core.Type.isNullOrEmpty(optionParames.modulename) ? optionParames.modulename : "";
                    entity["mcs_exceptiontime"] = Core.Type.isDate(optionParames.exceptiontime) ? optionParames.exceptiontime : new Date();
                    entity["mcs_queuedtime"] = Core.Type.isDate(optionParames.queuedtime) ? optionParames.queuedtime : new Date();
                    entity["mcs_dequeuedtime"] = Core.Type.isDate(optionParames.dequeuedtime) ? optionParames.dequeuedtime : new Date();

                    Da.createRecord("mcs_exceptionlog", entity, {
                        successCallback: optionParames.successCallback,
                        errorCallback: optionParames.errorCallback,
                    });
                }
            }
            window.setTimeout(asyncFunc, 0);
        };

        return {
            writeInfo: writeInfo,
            writeErr: writeErr
        };
    }());

    var Grid = (function () {

        var Row = (function () {
            var _row = function (rowControl) {
                top.window.rowtest = rowControl;
                this.rowControl = rowControl;
            }
            _row.prototype.getValue = function (attrName) {
                return this.rowControl.getAttribute(attrName).getValue();
            };

            _row.prototype.getId = function () {
                return Core.Guid.parse(this.rowControl.getData().getEntity().getId());
            };

            var create = function (rowControl) {
                return new _row(rowControl);
            }
            _row.create = create;
            return _row;
        }());

        var _grid = function (gridControl) {
            this.gridControl = gridControl;
        };

        _grid.prototype.getRowsLength = function () {
            return this.gridControl.getGrid().getRows().getLength();
        };

        _grid.prototype.refresh = function () {
            this.gridControl.refresh();
        };

        _grid.prototype.getSelectedRows = function () {
            var rows = [];
            this.gridControl.getGrid().getSelectedRows().forEach(function (item) {
                var row = new Row(item);
                rows.push(row);
            });
            return rows;
        };

        _grid.prototype.getSelectedRowsLength = function () {
            return this.gridControl.getGrid().getSelectedRows().getLength();
        };
        var create = function (gridControl) {
            return new _grid(gridControl);
        };

        _grid.create = create;

        return _grid;

    }());

    var Fc = (function () {
        var _fc = function (formContext) {
            this.formContext = formContext;
        };

        _fc.prototype.getId = function () {
            return Core.Guid.parse(this.formContext.data.entity.getId());
        };
        _fc.prototype.getValue = function (attrName) {
            var attrControl = this.formContext.data.entity.attributes.getByName(attrName);
            if (attrControl != null) {
                return attrControl.getValue();
            }
            return null;
        };
        _fc.prototype.setValue = function (attrName, value) {
            this.formContext.data.entity.attributes.getByName(attrName).setValue(value);
        };
        _fc.prototype.addPreSearch = function (attrName, initFunction) {
            this.formContext.getControl(attrName).addPreSearch(initFunction);
        }
        _fc.prototype.addCustomFilter = function (attrName, filter) {
            this.formContext.getControl(attrName).addCustomFilter(filter);
        };
        _fc.prototype.getGrid = function (name) {
            return Grid.create(this.formContext.getControl(name));
        };
        _fc.prototype.getControl = function (name) {
            return this.formContext.getControl(name);
        };
        _fc.prototype.getLookUpId = function (attrName) {
            var attrControl = this.formContext.data.entity.attributes.getByName(attrName);
            if (attrControl != null && attrControl.getValue() != null) {
                return Core.Guid.parse(attrControl.getValue()[0].id);
            }
            return null;
        };
        _fc.prototype.getLookUpName = function (attrName) {
            var attrControl = this.formContext.data.entity.attributes.getByName(attrName);
            if (attrControl != null) {
                return attrControl.getValue()[0].name;
            }
            return null;
        };


        /**
         * 保存数据
         * @param {object} optionParames 可选参数
         * @param {function(successCallbackParames)} optionParames.successCallback 成功后执行的函数
         * @param {function(errCallbackParames)} optionParames.errorsCallback 失败后执行的函数
         */
        _fc.prototype.save = function (optionParames) {
            optionParames = Core.Type.isObject(optionParames) ? optionParames : {};
            optionParames.successCallback = Core.Type.isFunction(optionParames.successCallback) ? optionParames.successCallback : null;
            optionParames.errorsCallback = Core.Type.isFunction(optionParames.errorsCallback) ? optionParames.errorsCallback : null;
            this.formContext.data.save().then(optionParames.successCallback, optionParames.errorCallback);
        };

        _fc.prototype.getIsDirty = function () {
            return this.formContext.data.getIsDirty();
        };

        _fc.prototype.isValid = function () {
            return this.formContext.data.isValid();
        }

        _fc.prototype.refresh = function (isSave, optionParames) {
            isSave = Core.Type.isBoolean(isSave) ? isSave : false;
            optionParames = Core.Type.isObject(optionParames) ? optionParames : {};
            optionParames.successCallback = Core.Type.isFunction(optionParames.successCallback) ? optionParames.successCallback : null;
            optionParames.errorsCallback = Core.Type.isFunction(optionParames.errorsCallback) ? optionParames.errorsCallback : null;
            this.formContext.data.refresh(isSave).then(optionParames.successCallback, optionParames.errorCallback);
        };

        _fc.prototype.refreshRibbon = function (refreshAll) {
            refreshAll = Core.Type.isBoolean(refreshAll) ? refreshAll : true;

            this.formContext.ui.refreshRibbon(refreshAll);
        }

        /**
         * 刷新窗体
         * @param {object} optionParames 可选参数
         * @param {function(successCallbackParames)} optionParames.successCallback 成功后执行的函数
         */
        _fc.prototype.refreshFormAndRibbon = function (optionParames) {
            optionParames = Core.Type.isObject(optionParames) ? optionParames : {};
            var that = this;
            this.refresh(false, {
                successCallback: function () {
                    that.refreshRibbon();

                    if (Core.Type.isFunction(optionParames.successCallback)) {
                        optionParames.successCallback();
                    }
                }
            });
        }

        _fc.prototype.setFocus = function (attrName) {
            this.formContext.getControl(attrName).setFocus();
        }

        _fc.prototype.getEntityName = function () {
            return this.formContext.data.entity.getEntityName();
        }

        _fc.prototype.getEntityReference = function () {
            return this.formContext.data.entity.getEntityReference()
        }

        _fc.prototype.setVisible = function (attrName, isVisible) {
            isVisible = Core.Type.isBoolean(isVisible) ? isVisible : true;
            this.formContext.getControl(attrName).setVisible(isVisible);
        }

        _fc.prototype.setDisabled = function (attrName, isDisabled) {
            isDisabled = Core.Type.isBoolean(isDisabled) ? isDisabled : true;
            this.formContext.getControl(attrName).setDisabled(isDisabled);
        }

        _fc.prototype.setDisabledAll = function (isDisabled) {
            isDisabled = Core.Type.isBoolean(isDisabled) ? isDisabled : true;
            var controls = this.formContext.ui.controls.get();
            for (var i in controls) {
                var control = controls[i];
                if (typeof control.setDisabled == "function") {
                    control.setDisabled(isDisabled);
                }
            }

        }


        _fc.prototype.setRequiredLevel = function (attrName, requirementLevel) {
            //none  required  recommended
            requirementLevel = Core.Type.isNullOrEmpty(requirementLevel) ? "required" : requirementLevel;
            this.formContext.getAttribute(attrName).setRequiredLevel(requirementLevel);
        }

        _fc.prototype.getAnnotationLength = function () {
            var fb = new DynaHx.Da.FetchXmlBuilder();
            var entityName = this.getEntityName();
            var entityId = entityName + "id";
            fb.select("annotationid").from("annotation");
            fb.link(entityName, entityId, "objectid", "ab", "inner");
            fb.filter("and");
            fb.condition(entityId, "=", this.getId().toString(true));
            fb.filterEnd();
            fb.linkEnd();
            var length = 0;
            Da.retrieveFromFetchxml("annotation", fb.toString(), {
                isAsync: false,
                successCallback: function (parames) {
                    length = parames.data.length;
                }
            })
            return length;
        };

        /**
         * 返回窗体状态
         * @return {number} 0、Undefined  1、Create  2、Update  3、Read Only  4、Disabled  6、Bulk Edit
         */
        _fc.prototype.getFormType = function () {
            return this.formContext.ui.getFormType();
        }

        var create = function (formContext) {
            return new _fc(formContext);
        };

        var createFromEcutionContext = function (executionContext) {
            return create(executionContext.getFormContext());
        };

        _fc.create = create;
        _fc.createFromEcutionContext = createFromEcutionContext;
        return _fc;

    }());

    var Da = (function () {

        var getClientUrl = function () {
            var clientUrl = XrmEx.Utility.getGlobalContext().getClientUrl();
            return clientUrl;
        };

        var getWebAPIPath = function () {
            return getClientUrl() + "/api/data/v9.1/";
        };

        var getHeaders = function (isPrefer, isInAdmin, pageCount) {
            isPrefer = Core.Type.isBoolean(isPrefer) ? isPrefer : true;
            isInAdmin = Core.Type.isBoolean(isInAdmin) ? isInAdmin : false;
            pageCount = Core.Type.isNumber(pageCount) ? pageCount : null;

            var heads = [];
            heads.push({ name: "Accept", value: "application/json" });
            heads.push({ name: "Content-Type", value: "application/json; charset=utf-8" });
            heads.push({ name: "OData-MaxVersion", value: "4.0" });
            heads.push({ name: "OData-Version", value: "4.0" });
            if (isPrefer || Core.Type.isNumber(pageCount)) {
                if (Core.Type.isNumber(pageCount)) {
                    heads.push({ name: "Prefer", value: "odata.include-annotations=\"*\",odata.maxpagesize=" + pageCount });
                } else {
                    heads.push({ name: "Prefer", value: "odata.include-annotations=\"*\"" });
                }

                //heads.push({ name: "Prefer", value: "odata.include-annotations=\"*\"" });
                //分页模式
                //heads.push({ name: "Prefer", value: "odata.include-annotations=\"*\",odata.maxpagesize=10" });
            }
            if (isInAdmin) {
                heads.push({ name: "MSCRMCallerID", value: "da8700a9-670c-eb11-a813-000d3ac69863" });
            }
            return heads;
        };

        var getBatchHeaders = function (isPrefer, isInAdmin, batch) {
            isPrefer = Core.Type.isBoolean(isPrefer) ? isPrefer : true;
            isInAdmin = Core.Type.isBoolean(isInAdmin) ? isInAdmin : false;
            var heads = [];
            heads.push({ name: "Accept", value: "application/json" });
            heads.push({ name: "Content-Type", value: "multipart/mixed; boundary=batch_" + batch });
            heads.push({ name: "OData-MaxVersion", value: "4.0" });
            heads.push({ name: "OData-Version", value: "4.0" });
            if (isPrefer) {
                heads.push({ name: "Prefer", value: "odata.include-annotations=\"*\"" });
            }
            if (isInAdmin) {
                heads.push({ name: "MSCRMCallerID", value: "00000000-0000-0000-0000-000000000000" });
            }
            return heads;
        };

        /**
         * 数据操作的可选参数对象
         * @typedef {object} headerParames
         * @property {boolean} isInAdmin 是否使用管理员身份操作
         * @property {number} pageCount 分页大小
         * @property {string} batchNo 批处理编号
         * @property {boolean} isPrefer 是否返回所有信息 默认是
         * @property {string} etag 是否加入版本号
         */
        /**
         * 初始化可选参数对象
         * @param {headerParames} headerParames 组装请求头的可选参数对象
         */
        var generateHeaders = function (headerParames) {
            headerParames = Core.Type.isObject(headerParames) ? headerParames : {};
            headerParames.isInAdmin = Core.Type.isBoolean(headerParames.isInAdmin) ? headerParames.isInAdmin : false;
            headerParames.pageCount = Core.Type.isNumber(headerParames.pageCount) ? headerParames.pageCount : null;
            headerParames.batchNo = !Core.Type.isNullOrEmpty(headerParames.batch) ? headerParames.batch : null;
            headerParames.isPrefer = Core.Type.isBoolean(headerParames.isPrefer) ? headerParames.isPrefer : true;
            headerParames.etag = !Core.Type.isNullOrEmpty(headerParames.etag) ? headerParames.etag : null;

            var heads = [];
            heads.push({ name: "Accept", value: "application/json" });
            heads.push({ name: "OData-MaxVersion", value: "4.0" });
            heads.push({ name: "OData-Version", value: "4.0" });

            if (!Core.Type.isNullOrEmpty(headerParames.batch))
                heads.push({ name: "Content-Type", value: "multipart/mixed; boundary=batch_" + headerParames.batch });
            else
                heads.push({ name: "Content-Type", value: "application/json; charset=utf-8" });

            if (headerParames.isPrefer)
                if (Core.Type.isNumber(headerParames.pageCount) && headerParames.pageCount > 0)
                    heads.push({ name: "Prefer", value: "odata.include-annotations=\"*\",odata.maxpagesize=" + headerParames.pageCount });
                else
                    heads.push({ name: "Prefer", value: "odata.include-annotations=\"*\"" });

            if (headerParames.isInAdmin)
                heads.push({ name: "MSCRMCallerID", value: "00000000-0000-0000-0000-000000000000" });

            if (!Core.Type.isNullOrEmpty(headerParames.etag))
                heads.push({ name: "If-Match", value: headerParames.etag });
            return heads;
        };


        var getEntityApiName = function (entityLogicalName) {
            if (entityLogicalName.substring(entityLogicalName.length - 1) == "s") {
                return entityLogicalName + "es";
            }
            else if (entityLogicalName.substring(entityLogicalName.length - 1) == "y") {
                return entityLogicalName.substring(0, entityLogicalName.length - 1) + "ies";
            }
            else {
                return entityLogicalName + "s";
            }
        };
        /**
         * 数据操作的可选参数对象
         * @typedef {object} daOptionParames
         * @property {boolean} isInAdmin 是否使用管理员身份操作
         * @property {boolean} isAsync 是否使用异步操作 默认是
         * @property {boolean} isAlwaysAjax 是否始终使用Ajax进行操作 默认否
         * @property {boolean} isDialogErr 是否在出错后弹出错误提示 默认是
         * @property {function(successCallbackParames)} optionParames.successCallback 成功后执行的函数
         * @property {function(errorCallbackParames)} optionParames.errorCallback 失败后执行的函数
         */
        /**
         * 初始化可选参数对象
         * @param {daOptionParames} optionParames 可选参数对象
         */
        var createoptionParames = function (optionParames) {
            optionParames = !Core.Type.isNull(optionParames) ? optionParames : {};
            optionParames.successCallback = Core.Type.isFunction(optionParames.successCallback) ? optionParames.successCallback : null;
            optionParames.errorCallback = Core.Type.isFunction(optionParames.successCallback) ? optionParames.errorCallback : null;
            optionParames.isInAdmin = Core.Type.isBoolean(optionParames.isInAdmin) ? optionParames.isInAdmin : false;
            optionParames.isAsync = Core.Type.isBoolean(optionParames.isAsync) ? optionParames.isAsync : true;
            optionParames.isAlwaysAjax = Core.Type.isBoolean(optionParames.isAlwaysAjax) ? optionParames.isAlwaysAjax : false;
            optionParames.isDialogErr = Core.Type.isBoolean(optionParames.isDialogErr) ? optionParames.isDialogErr : true;
            return optionParames;
        };
        /**
         * 创建记录 成功后回调函数返回新记录的Guid
         * @param {string} entityLogicalName 实体名称(不需要加复数形式)
         * @param {object} data 实体参数对象
         * @param {daOptionParames} optionParames 可选参数对象
         */
        var createRecord = function (entityLogicalName, data, optionParames) {
            optionParames = createoptionParames(optionParames);
            if (optionParames.isAsync && !optionParames.isInAdmin && !optionParames.isAlwaysAjax) {
                var apiParames = {
                    entityLogicalName: entityLogicalName,
                    data: data,
                    successCallback: function (result) {
                        if (Core.Type.isFunction(optionParames.successCallback)) {
                            var successCallbackParames = {
                                id: result.id,
                                newEntityId: result.id
                            };
                            optionParames.successCallback(successCallbackParames);
                        }
                    },
                    errorCallback: function (result) {
                        if (optionParames.isDialogErr) {
                            Bus.openErrorDialog(result.message, result.code);
                        }
                        if (Core.Type.isFunction(optionParames.errorCallback)) {
                            var errorCallbackParames = {
                                message: result.message,
                                code: result.code
                            };
                            optionParames.errorCallback(errorCallbackParames);
                        }
                    }
                };
                XrmEx.WebApi.createRecord(apiParames);
            }
            else {
                var ajaxParames = {
                    url: getWebAPIPath() + getEntityApiName(entityLogicalName),
                    method: "POST",
                    data: JSON.stringify(data),
                    headers: getHeaders(true, optionParames.isInAdmin),
                    async: optionParames.isAsync,
                    handles: [
                        {
                            multipleStates: [200, 204],
                            callback: function (response, xhr) {
                                if (Core.Type.isFunction(optionParames.successCallback)) {
                                    var uri = xhr.getResponseHeader("OData-EntityId");
                                    var regExp = /\(([^)]+)\)/;
                                    var matches = regExp.exec(uri);
                                    var newEntityId = matches[1];
                                    var successCallbackParames = {
                                        id: newEntityId,
                                        newEntityId: newEntityId
                                    };
                                    optionParames.successCallback(successCallbackParames);
                                }
                            }
                        }
                    ],
                    otherCallback: function (response) {
                        var result = JSON.parse(response);
                        if (optionParames.isDialogErr) {
                            Bus.openErrorDialog(result.error.message, parseInt(result.error.code));
                        }
                        if (Core.Type.isFunction(optionParames.errorCallback)) {
                            var errorCallbackParames = {
                                message: result.error.message,
                                code: result.error.code
                            };
                            optionParames.errorCallback(errorCallbackParames);
                        }
                    }
                };
                Core.Ajax.send(ajaxParames);
            }
        };


        /**
         * 修改实体的可选参数对象
         * @typedef {object} updateRecordOptionParames
         * @property {boolean} isInAdmin 是否使用管理员身份操作
         * @property {boolean} isAsync 是否使用异步操作 默认是
         * @property {boolean} isAlwaysAjax 是否始终使用Ajax进行操作 默认否
         * @property {boolean} isDialogErr 是否在出错后弹出错误提示 默认是
         * @property {string} etag 版本号
         * @property {function(successCallbackParames)} optionParames.successCallback 成功后执行的函数
         * @property {function(errorCallbackParames)} optionParames.errorCallback 失败后执行的函数
         */

        /**
         * 修改记录
         * @param {string} entityLogicalName 实体名称(不需要加复数形式)
         * @param {string} id   实体的Guid
         * @param {object} data 实体参数对象
         * @param {updateRecordOptionParames} optionParames 可选参数对象
         */
        var updateRecord = function (entityLogicalName, id, data, optionParames) {
            optionParames = createoptionParames(optionParames);
            if (!optionParames.isAsync || optionParames.isInAdmin || optionParames.isAlwaysAjax || !Core.Type.isNullOrEmpty(optionParames.etag)) {
                var ajaxParames = {
                    url: getWebAPIPath() + getEntityApiName(entityLogicalName) + "(" + id + ")",
                    method: "PATCH",
                    data: JSON.stringify(data),
                    headers: generateHeaders({
                        isInAdmin: optionParames.isInAdmin,
                        etag: optionParames.etag
                    }),
                    async: optionParames.isAsync,
                    handles: [
                        {
                            multipleStates: [200, 204],
                            callback: function (response, xhr) {
                                if (Core.Type.isFunction(optionParames.successCallback)) {
                                    var successCallbackParames = {};
                                    optionParames.successCallback(successCallbackParames);
                                }
                            }
                        }
                    ],
                    otherCallback: function (response) {
                        var result = JSON.parse(response);
                        if (optionParames.isDialogErr) {
                            Bus.openErrorDialog(result.error.message, parseInt(result.error.code));
                        }
                        if (Core.Type.isFunction(optionParames.errorCallback)) {
                            var errorCallbackParames = {
                                message: result.error.message,
                                code: result.error.code
                            };
                            optionParames.errorCallback(errorCallbackParames);
                        }
                    }

                };
                Core.Ajax.send(ajaxParames);
            }
            else {
                var apiParames = {
                    entityLogicalName: entityLogicalName,
                    id: id,
                    data: data,
                    successCallback: function (result) {
                        if (Core.Type.isFunction(optionParames.successCallback)) {
                            var successCallbackParames = null;
                            optionParames.successCallback(successCallbackParames);
                        }
                    },
                    errorCallback: function (result) {
                        if (optionParames.isDialogErr) {
                            Bus.openErrorDialog(result.message, result.code);
                        }
                        if (Core.Type.isFunction(optionParames.errorCallback)) {
                            var errorCallbackParames = {
                                message: result.message,
                                code: result.code
                            };
                            optionParames.errorCallback(errorCallbackParames);
                        }
                    }
                };
                XrmEx.WebApi.updateRecord(apiParames);
            }
        };


        /**
         * 修改字段
         * @param {string} entityLogicalName 实体名称(不需要加复数形式)
         * @param {string} id   实体的Guid
         * @param {string} field 要修改的字段
         * @param {object} value 要修改的值
         * @param {daOptionParames} optionParames 可选参数对象
         */
        var updateField = function (entityLogicalName, id, field, value, optionParames) {
            optionParames = createoptionParames(optionParames);
            var parames = {
                url: getWebAPIPath() + getEntityApiName(entityLogicalName) + "(" + id + ")/" + field,
                method: "PUT",
                data: JSON.stringify({ "value": value }),
                headers: generateHeaders({
                    isInAdmin: optionParames.isInAdmin
                }),
                async: optionParames.isAsync,
                handles: [
                    {
                        multipleStates: [200, 204],
                        callback: function (response, xhr) {
                            if (Core.Type.isFunction(optionParames.successCallback)) {
                                var successCallbackParames = null;
                                optionParames.successCallback(successCallbackParames);
                            }
                        }
                    }
                ],
                otherCallback: function (response) {
                    var result = JSON.parse(response);
                    if (optionParames.isDialogErr) {
                        Bus.openErrorDialog(result.error.message, parseInt(result.error.code));
                    }
                    if (Core.Type.isFunction(optionParames.errorCallback)) {
                        var errorCallbackParames = {
                            message: result.error.message,
                            code: result.error.code
                        };
                        optionParames.errorCallback(errorCallbackParames);
                    }
                }

            };
            Core.Ajax.send(parames);
        };
        /**
         * 删除记录
         * @param {string} entityLogicalName 实体名称(不需要加复数形式)
         * @param {string} id   实体的Guid
         * @param {daOptionParames} optionParames 可选参数对象
         */
        var deleteRecord = function (entityLogicalName, id, optionParames) {
            optionParames = createoptionParames(optionParames);
            if (optionParames.isAsync && !optionParames.isInAdmin && !optionParames.isAlwaysAjax) {
                var apiParames = {
                    entityLogicalName: entityLogicalName,
                    id: id,
                    successCallback: function (result) {
                        if (Core.Type.isFunction(optionParames.successCallback)) {
                            var successCallbackParames = null;
                            optionParames.successCallback(successCallbackParames);
                        }
                    },
                    errorCallback: function (result) {
                        if (optionParames.isDialogErr) {
                            Bus.openErrorDialog(result.message, result.code);
                        }
                        if (Core.Type.isFunction(optionParames.errorCallback)) {
                            var errorCallbackParames = {
                                message: result.message,
                                code: result.code
                            };
                            optionParames.errorCallback(errorCallbackParames);
                        }
                    }
                };
                XrmEx.WebApi.deleteRecord(apiParames);
            }
            else {
                var ajaxParames = {
                    url: getWebAPIPath() + getEntityApiName(entityLogicalName) + "(" + id + ")",
                    method: "DELETE",
                    headers: getHeaders(true, optionParames.isInAdmin),
                    async: optionParames.isAsync,
                    handles: [
                        {
                            multipleStates: [200, 204],
                            callback: function (response, xhr) {
                                if (Core.Type.isFunction(optionParames.successCallback)) {
                                    var successCallbackParames = {};
                                    optionParames.successCallback(successCallbackParames);
                                }
                            }
                        }
                    ],
                    otherCallback: function (response) {
                        var result = JSON.parse(response);
                        if (optionParames.isDialogErr) {
                            Bus.openErrorDialog(result.error.message, parseInt(result.error.code));
                        }
                        if (Core.Type.isFunction(optionParames.errorCallback)) {
                            var errorCallbackParames = {
                                message: result.error.message,
                                code: result.error.code
                            };
                            optionParames.errorCallback(errorCallbackParames);
                        }
                    }
                };
                Core.Ajax.send(ajaxParames);
            }
        };
        /**
         * 查询选项集
         * @param {string} entityLogicalName 实体名称(不需要加复数形式)
         * @param {string} optionsetName   选项集的名称
         * @param {daOptionParames} optionParames 可选参数对象
         */
        var retrieveOptions = function (entityLogicalName, optionsetName, optionParames) {
            optionParames = createoptionParames(optionParames);
            var parames = {
                url: getWebAPIPath() + "EntityDefinitions(LogicalName=" + "'" + entityLogicalName + "'" + ")/Attributes(LogicalName=" + "'" + optionsetName + "'" + ")/Microsoft.Dynamics.CRM.PicklistAttributeMetadata?$select=LogicalName&$expand=GlobalOptionSet($select=Options)",
                method: "GET",
                headers: getHeaders(true, optionParames.isInAdmin),
                async: optionParames.isAsync,
                handles: [
                    {
                        multipleStates: [200, 204],
                        callback: function (response, xhr) {
                            if (Core.Type.isFunction(optionParames.successCallback)) {

                                var results = JSON.parse(response);
                                var successCallbackParames = [];
                                results.GlobalOptionSet.Options.forEach(function (item) {
                                    successCallbackParames.push({ value: item.Value, Text: item.Label.UserLocalizedLabel.Label });
                                });

                                optionParames.successCallback(successCallbackParames);
                            }
                        }
                    }
                ],
                otherCallback: function (response) {
                    var result = JSON.parse(response);
                    if (optionParames.isDialogErr) {
                        Bus.openErrorDialog(result.error.message, parseInt(result.error.code));
                    }
                    if (Core.Type.isFunction(optionParames.errorCallback)) {
                        var errorCallbackParames = {
                            message: result.error.message,
                            code: result.error.code
                        };
                        optionParames.errorCallback(errorCallbackParames);
                    }
                }
            };
            Core.Ajax.send(parames);
        };
        /**
         * 删除关系
         * @param {string} entityLogicalName 实体名称(不需要加复数形式)
         * @param {string} id  实体的Guid
         * @param {string} relationshipName  关系名称
         * @param {string} relatedId  关系的Guid
         * @param {daOptionParames} optionParames 可选参数对象
         */
        var disassociateRecord = function (entityLogicalName, id, relationshipName, relatedId, optionParames) {
            optionParames = createoptionParames(optionParames);
            var parames = {
                url: getWebAPIPath() + getEntityApiName(entityLogicalName) + "(" + id + ")/" + getEntityApiName(relationshipName) + "(" + relatedId + ")/$ref",
                method: "DELETE",
                headers: getHeaders(true, optionParames.isInAdmin),
                async: optionParames.isAsync,
                handles: [
                    {
                        multipleStates: [200, 204],
                        callback: function (response, xhr) {
                            if (Core.Type.isFunction(optionParames.successCallback)) {
                                var successCallbackParames = null;
                                optionParames.successCallback(successCallbackParames);
                            }
                        }
                    }
                ],
                otherCallback: function (response) {
                    var result = JSON.parse(response);
                    if (optionParames.isDialogErr) {
                        Bus.openErrorDialog(result.error.message, parseInt(result.error.code));
                    }
                    if (Core.Type.isFunction(optionParames.errorCallback)) {
                        var errorCallbackParames = {
                            message: result.error.message,
                            code: result.error.code
                        };
                        optionParames.errorCallback(errorCallbackParames);
                    }
                }
            };
            Core.Ajax.send(parames);

        };
        /**
         * 添加一条关系
         * @param {string} entityLogicalName 实体名称(不需要加复数形式)
         * @param {string} id  实体的Guid
         * @param {string} relationshipName  关系名称
         * @param {string} relatedId  关系的Guid
         * @param {daOptionParames} optionParames 可选参数对象
         */
        var associateRecord = function (entityLogicalName, id, relationshipName, relatedId, optionParames) {
            optionParames = createoptionParames(optionParames);
            var association = { "@odata.id": getWebAPIPath() + optionParames(relatedEntitySetName) + "(" + relatedId + ")" };
            var parames = {
                url: getWebAPIPath() + optionParames(entityLogicalName) + "(" + id + ")/" + optionParames(relationshipName) + "/$ref",
                method: "POST",
                data: JSON.stringify(association),
                headers: getHeaders(true, optionParames.isInAdmin),
                async: optionParames.isAsync,
                handles: [
                    {
                        multipleStates: [200, 204],
                        callback: function (response, xhr) {
                            if (Core.Type.isFunction(optionParames.successCallback)) {
                                var successCallbackParames = null;
                                optionParames.successCallback(successCallbackParames);
                            }
                        }
                    }
                ],
                otherCallback: function (response) {
                    var result = JSON.parse(response);
                    if (optionParames.isDialogErr) {
                        Bus.openErrorDialog(result.error.message, parseInt(result.error.code));
                    }
                    if (Core.Type.isFunction(optionParames.errorCallback)) {
                        var errorCallbackParames = {
                            message: result.error.message,
                            code: result.error.code
                        };
                        optionParames.errorCallback(errorCallbackParames);
                    }
                }
            };
            Core.Ajax.send(parames);
        };
        /**
         * 调用操作
         * @param {string} actionName 操作名称
         * @param {object} actionparames  操作的参数
         * @param {daOptionParames} optionParames 可选参数对象
         */
        var invokeAction = function (actionName, actionparames, optionParames) {

            optionParames = createoptionParames(optionParames);
            var parames = {
                url: getWebAPIPath() + actionName,
                method: "POST",
                headers: getHeaders(true, optionParames.isInAdmin),
                data: JSON.stringify(actionparames),
                async: optionParames.isAsync,
                handles: [
                    {
                        multipleStates: [200, 204],
                        callback: function (response) {

                            if (Core.Type.isFunction(optionParames.successCallback)) {
                                var result = JSON.parse(response);
                                var successCallbackParames = {};
                                successCallbackParames.data = result;
                                optionParames.successCallback(successCallbackParames);
                            }
                        }
                    }
                ],
                otherCallback: function (response) {

                    var result = JSON.parse(response);
                    if (optionParames.isDialogErr) {
                        Bus.openErrorDialog(result.error.message, parseInt(result.error.code));
                    }
                    if (Core.Type.isFunction(optionParames.errorCallback)) {
                        var errorCallbackParames = {
                            message: result.error.message,
                            code: result.error.code
                        };
                        optionParames.errorCallback(errorCallbackParames);
                    }
                }
            };
            Core.Ajax.send(parames);
        };
        /**
         * 通过实体Guid获取数据
         * @param {string} entityLogicalName 实体名称(不需要加复数形式)
         * @param {id} actionparames  实体的Guid
         * @param {daOptionParames} optionParames 可选参数对象
         */
        var retrieveFromEntityId = function (entityLogicalName, id, optionParames) {
            optionParames = createoptionParames(optionParames);
            var parames = {
                url: getWebAPIPath() + getEntityApiName(entityLogicalName) + "(" + id + ")",
                method: "GET",
                headers: getHeaders(true, optionParames.isInAdmin),
                async: optionParames.isAsync,
                handles: [
                    {
                        multipleStates: [200, 204],
                        callback: function (response) {
                            if (Core.Type.isFunction(optionParames.successCallback)) {
                                var results = JSON.parse(response);
                                var successCallbackParames = {};
                                successCallbackParames.data = new Core.Entity(entityLogicalName, results);
                                optionParames.successCallback(successCallbackParames);
                            }
                        }
                    }
                ],
                otherCallback: function (response) {
                    var result = JSON.parse(response);
                    if (optionParames.isDialogErr) {
                        Bus.openErrorDialog(result.error.message, parseInt(result.error.code));
                    }
                    if (Core.Type.isFunction(optionParames.errorCallback)) {

                        var errorCallbackParames = {
                            message: result.error.message,
                            code: result.error.code
                        };
                        optionParames.errorCallback(errorCallbackParames);
                    }
                }
            };
            Core.Ajax.send(parames);
        };


        /**
         * 通过FetchXml获取数据的可选参数对象
         * @typedef {object} retrieveFromFetchxmlOptionParames
         * @property {boolean} isInAdmin 是否使用管理员身份操作
         * @property {boolean} isAsync 是否使用异步操作 默认是
         * @property {boolean} isAlwaysAjax 是否始终使用Ajax进行操作 默认否
         * @property {boolean} isDialogErr 是否在出错后弹出错误提示 默认是
         * @property {number} pageCount 分页大小
         * @property {function(successCallbackParames)} optionParames.successCallback 成功后执行的函数
         * @property {function(errorCallbackParames)} optionParames.errorCallback 失败后执行的函数
         */

        /**
         * 通过FetchXml获取数据
         * @param {string} entityLogicalName 实体名称(不需要加复数形式)
         * @param {string} fetchxml  fetchxml
         * @param {retrieveFromFetchxmlOptionParames} optionParames 可选参数对象
         */
        var retrieveFromFetchxml = function (entityLogicalName, fetchxml, optionParames) {
            optionParames = createoptionParames(optionParames);
            optionParames.pageCount = Core.Type.isNumber(optionParames.pageCount) ? optionParames.pageCount : null;
            var parames = {
                url: getWebAPIPath() + getEntityApiName(entityLogicalName),
                method: "GET",
                headers: getHeaders(true, optionParames.isInAdmin, optionParames.pageCount),
                data: { fetchXml: fetchxml },
                async: optionParames.isAsync,
                handles: [
                    {
                        multipleStates: [200, 204],
                        callback: function (response) {
                            if (Core.Type.isFunction(optionParames.successCallback)) {
                                var successCallbackParames = {};
                                successCallbackParames.data = [];
                                var results = JSON.parse(response);
                                results.value.forEach(function (item) {
                                    successCallbackParames.data.push(new Core.Entity(entityLogicalName, item));
                                });
                                optionParames.successCallback(successCallbackParames);
                            }
                        }
                    }
                ],
                otherCallback: function (response) {

                    var result = JSON.parse(response);
                    if (optionParames.isDialogErr) {
                        Bus.openErrorDialog(result.error.message, parseInt(result.error.code));
                    }
                    if (Core.Type.isFunction(optionParames.errorCallback)) {
                        var errorCallbackParames = {
                            message: result.error.message + "fetchxml=" + fetchxml,
                            //message: result.error.message,
                            code: result.error.code
                        };
                        optionParames.errorCallback(errorCallbackParames);
                    }
                }
            };
            Core.Ajax.send(parames);
        };

        /**
         * 通过查询参数获取数据
         * @param {string} entityLogicalName 实体名称(不需要加复数形式)
         * @param {string} query  查询以及排序参数
         * @param {daOptionParames} optionParames 可选参数对象
         */
        var retrieveFromQuery = function (entityLogicalName, query, optionParames) {
            optionParames = createoptionParames(optionParames);
            var parames = {
                url: getWebAPIPath() + getEntityApiName(entityLogicalName) + "?" + query,
                method: "GET",
                headers: getHeaders(true, optionParames.isInAdmin),
                async: optionParames.isAsync,
                handles: [
                    {
                        multipleStates: [200, 204],
                        callback: function (response) {

                            if (Core.Type.isFunction(optionParames.successCallback)) {
                                var successCallbackParames = {};
                                successCallbackParames.data = [];
                                var results = JSON.parse(response);
                                results.value.forEach(function (item) {
                                    successCallbackParames.data.push(new Core.Entity(entityLogicalName, item));
                                });
                                optionParames.successCallback(successCallbackParames);
                            }
                        }
                    }
                ],
                otherCallback: function (response) {

                    var result = JSON.parse(response);
                    if (optionParames.isDialogErr) {
                        Bus.openErrorDialog(result.error.message, parseInt(result.error.code));
                    }
                    if (Core.Type.isFunction(optionParames.errorCallback)) {
                        var errorCallbackParames = {
                            message: result.error.message,
                            code: result.error.code
                        };
                        optionParames.errorCallback(errorCallbackParames);
                    }
                }
            };
            Core.Ajax.send(parames);
        };


        /**
         * 通过查询参数获取数据
         * @param {string} entityLogicalName 实体名称(不需要加复数形式)
         * @param {string} entityLogicalName 实体Id
         * @param {string} query  查询以及排序参数
         * @param {daOptionParames} optionParames 可选参数对象
        */
        var retrieveRecord = function (entityLogicalName, entityId, query, optionParames) {
            optionParames = createoptionParames(optionParames);
            var parames = {
                url: getWebAPIPath() + getEntityApiName(entityLogicalName) + "(" + entityId + ")?" + query,
                method: "GET",
                headers: getHeaders(true, optionParames.isInAdmin),
                async: optionParames.isAsync,
                handles: [
                    {
                        multipleStates: [200, 204],
                        callback: function (response) {
                            if (Core.Type.isFunction(optionParames.successCallback)) {
                                var results = JSON.parse(response);
                                var successCallbackParames = {};
                                successCallbackParames.data = new Core.Entity(entityLogicalName, results);
                                optionParames.successCallback(successCallbackParames);
                            }
                        }
                    }
                ],
                otherCallback: function (response) {
                    var result = JSON.parse(response);
                    if (optionParames.isDialogErr) {
                        Bus.openErrorDialog(result.error.message, parseInt(result.error.code));
                    }
                    if (Core.Type.isFunction(optionParames.errorCallback)) {
                        var errorCallbackParames = {
                            message: result.error.message,
                            code: result.error.code
                        };
                        optionParames.errorCallback(errorCallbackParames);
                    }
                }
            };
            Core.Ajax.send(parames);
        };

        /**
         * 执行批处理操作
         * @param {BatchBuilder} batchBuilder 批处理操作对象
         * @param {daOptionParames} optionParames 可选参数对象
         */
        var executeBatch = function (batchBuilder, optionParames) {
            optionParames = createoptionParames(optionParames);
            var parames = {
                url: getWebAPIPath() + "$batch",
                method: "POST",
                headers: getBatchHeaders(true, optionParames.isInAdmin, batchBuilder.batch),
                data: batchBuilder.toString(),
                async: optionParames.isAsync,
                handles: [
                    {
                        multipleStates: [200, 204],
                        callback: function (response, xhr) {
                            if (Core.Type.isFunction(optionParames.successCallback)) {
                                var successCallbackParames = {
                                    message: response
                                };
                                optionParames.successCallback(successCallbackParames);
                            }
                        }
                    }
                ],
                otherCallback: function (response) {
                    if (optionParames.isDialogErr) {
                        Bus.openErrorDialog(response, 0, response);
                    }
                    if (Core.Type.isFunction(optionParames.errorCallback)) {
                        var errorCallbackParames = {
                            message: response
                        };
                        optionParames.errorCallback(errorCallbackParames);
                    }
                }
            };
            Core.Ajax.send(parames);
        };
        /**
         * 批处理操作对象
         * @typedef {object} BatchBuilder
         */
        var BatchBuilder = (function () {
            var _BatchBuilder = function () {
                this.content = new Core.StringBuilder();
                this.changeset = Core.Guid.newGuid().toString();
                this.batch = Core.Guid.newGuid().toString();
                this.index = 0;
            };
            /**
             * 加入添加的批处理操作
             * @param {string} entityLogicalName 实体名称(不需要加复数形式)
             * @param {object} data 实体参数对象
             */
            _BatchBuilder.prototype.addPostData = function (entityLogicalName, data) {
                this.index++;
                this.content.appendLine('--changeset_' + this.changeset);
                this.content.appendLine('Content-Type:application/http');
                this.content.appendLine('Content-Transfer-Encoding:binary');
                this.content.appendLine('Content-ID:' + this.index);
                this.content.appendLine('');
                this.content.appendLine('POST ' + getWebAPIPath() + getEntityApiName(entityLogicalName) + ' HTTP/1.1');
                this.content.appendLine('Content-Type:application/json;type=entry');
                this.content.appendLine('');
                this.content.appendLine(JSON.stringify(data));
            };
            /**
             * 加入修改的批处理操作
             * @param {string} entityLogicalName 实体名称(不需要加复数形式)
             * @param {string} entityId 实体的Guid
             * @param {object} data 实体参数对象
             */
            _BatchBuilder.prototype.addPatchData = function (entityLogicalName, entityId, data, etag) {
                this.index++;
                this.content.appendLine('--changeset_' + this.changeset);
                this.content.appendLine('Content-Type:application/http');
                this.content.appendLine('Content-Transfer-Encoding:binary');


                this.content.appendLine('Content-ID:' + this.index);
                this.content.appendLine('');
                this.content.appendLine('PATCH ' + getWebAPIPath() + getEntityApiName(entityLogicalName) + '(' + entityId + ') HTTP/1.1');
                this.content.appendLine('Content-Type:application/json;type=entry');
                if (!Core.Type.isNullOrEmpty(etag))
                    this.content.appendLine('If-Match:' + etag);
                this.content.appendLine('');
                this.content.appendLine(JSON.stringify(data));
            };
            /**
             * 加入删除的批处理操作
             * @param {string} entityLogicalName 实体名称(不需要加复数形式)
             * @param {string} entityId 实体的Guid
             */
            _BatchBuilder.prototype.addDeleteData = function (entityLogicalName, entityId) {
                this.index++;
                this.content.appendLine('--changeset_' + this.changeset);
                this.content.appendLine('Content-Type:application/http');
                this.content.appendLine('Content-Transfer-Encoding:binary');
                this.content.appendLine('Content-ID:' + this.index);
                this.content.appendLine('');
                this.content.appendLine('DELETE ' + getWebAPIPath() + getEntityApiName(entityLogicalName) + '(' + entityId + ') HTTP/1.1');
                this.content.appendLine('Content-Type:application/json;type=entry');
                this.content.appendLine('');
            };

            /**
             * 加入删除LookUp的批处理操作
             * @param {string} entityLogicalName 实体名称(不需要加复数形式)
             * @param {string} entityId 实体的Guid
             * @param {string} refAttrName 要删除的LookUp属性
             */
            _BatchBuilder.prototype.addDeleteRef = function (entityLogicalName, entityId, refAttrName) {
                this.index++;
                this.content.appendLine('--changeset_' + this.changeset);
                this.content.appendLine('Content-Type:application/http');
                this.content.appendLine('Content-Transfer-Encoding:binary');
                this.content.appendLine('Content-ID:' + this.index);
                this.content.appendLine('');
                this.content.appendLine('DELETE ' + getWebAPIPath() + getEntityApiName(entityLogicalName) + '(' + entityId + ')/' + refAttrName + '/$ref HTTP/1.1');
                this.content.appendLine('Content-Type:application/json;type=entry');
                this.content.appendLine('');
            };
            /**
             * 返回字符串形式的批处理文本
             */
            _BatchBuilder.prototype.toString = function () {
                var sb = new Core.StringBuilder();
                sb.appendLine('--batch_' + this.batch);
                sb.appendLine('Content-Type: multipart/mixed;boundary=changeset_' + this.changeset);
                sb.appendLine('');
                sb.append(this.content.toString());
                sb.appendLine('--batch_' + this.batch + '--');
                return sb.toString();
            };
            return _BatchBuilder;
        }());
        /**
         * FetchXmlBuilder组装的辅助对象
         * @typedef {object} FetchXmlBuilder
         */
        var FetchXmlBuilder = (function () {
            var _FetchXmlBuilder = function () {
                this.content = new Core.StringBuilder();
                this.entityName = "";
            };

            var operatorConversion = function (operator) {
                switch (operator) {
                    case ">":
                        return "gt";
                    case ">=":
                        return "ge";
                    case "=":
                        return "eq";
                    case "<":
                        return "lt";
                    case "<=":
                        return "le";
                    case "<>":
                        return "ne";
                    case "dt<="://当前时间小于等于
                        return "on-or-after";
                    case "dt>="://当前时间大于等于
                        return "on-or-before";
                }
                return operator;
            }

            _FetchXmlBuilder.prototype.from = function (entityName) {
                this.entityName = entityName;
                return this;
            };

            _FetchXmlBuilder.prototype.select = function (attr) {
                var that = this;
                if (Core.Type.isArray(attr)) {
                    attr.forEach(function (item) {
                        that.content.append('<attribute name="' + item + '" />');
                    });
                }
                else {
                    this.content.append('<attribute name="' + attr + '" />');
                }
                return this;
            };

            _FetchXmlBuilder.prototype.selectAll = function () {
                this.content.append('<all-attributes/>');
                return this;
            };

            _FetchXmlBuilder.prototype.order = function (attrName, isdescending) {
                isdescending = Core.Type.isBoolean(isdescending) ? isdescending : true;
                this.content.append('<order attribute="' + attrName + '" descending="' + isdescending + '" />');
                return this
            }

            _FetchXmlBuilder.prototype.filter = function (type) {
                type = type === "or" || type === "and" ? type : "and";
                this.content.append('<filter type="' + type + '">');
                return this;
            }

            _FetchXmlBuilder.prototype.filterEnd = function () {
                this.content.append('</filter>');
                return this;
            }

            _FetchXmlBuilder.prototype.condition = function (attrName, op, val) {
                val = !Core.Type.isNullOrEmpty(val) ? 'value="' + val + '"' : '';
                this.content.append('<condition attribute="' + attrName + '" operator="' + operatorConversion(op) + '" ' + val + ' />');
                return this;
            }

            _FetchXmlBuilder.prototype.conditionIn = function (attrName, vals) {
                var that = this;
                vals = Core.Type.isArray(vals) ? vals : [];
                this.content.append('<condition attribute="' + attrName + '" operator="in" >');
                vals.forEach(function (item) {
                    that.content.append('<value>' + item + '</value>');
                });
                this.content.append('</condition>');
                return this;
            }


            _FetchXmlBuilder.prototype.link = function (name, from, to, alias, linkType) {
                linkType = !Core.Type.isNullOrEmpty(linkType) ? 'link-type="' + linkType + '"' : '';
                alias = !Core.Type.isNullOrEmpty(alias) ? 'alias="' + alias + '"' : '';
                this.content.append('<link-entity name="' + name + '" from="' + from + '" to="' + to + '" visible="false" ' + linkType + ' ' + alias + '>');
                return this;
            }

            _FetchXmlBuilder.prototype.linkEnd = function () {
                this.content.append('</link-entity>');
                return this;
            }

            _FetchXmlBuilder.prototype.append = function (content) {
                this.content.append(content);
                return this;
            }

            _FetchXmlBuilder.prototype.toString = function () {
                var sb = new Core.StringBuilder()
                sb.append('<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false">');
                sb.append('<entity name="' + this.entityName + '">');
                sb.append(this.content.toString());
                sb.append('</entity>');
                sb.append('</fetch>');
                return sb.toString();
            }

            _FetchXmlBuilder.prototype.getContent = function () {
                return this.content.toString();
            }
            return _FetchXmlBuilder;

        }());

        return {
            getEntityApiName: getEntityApiName,
            createRecord: createRecord,
            updateRecord: updateRecord,
            deleteRecord: deleteRecord,
            updateField: updateField,
            retrieveOptions: retrieveOptions,
            disassociateRecord: disassociateRecord,
            associateRecord: associateRecord,
            invokeAction: invokeAction,
            retrieveFromEntityId: retrieveFromEntityId,
            retrieveFromFetchxml: retrieveFromFetchxml,
            retrieveFromQuery: retrieveFromQuery,
            retrieveRecord: retrieveRecord,
            executeBatch: executeBatch,
            BatchBuilder: BatchBuilder,
            FetchXmlBuilder: FetchXmlBuilder
        };
    }());

    var Bus = (function () {

        var getResourceUrl = function () {
            return "mcs_/Resources/DynaHx";
        };

        var getLanguageId = function () {
            return XrmEx.Utility.getGlobalContext().userSettings.languageId;
        };

        var getCurrentUserId = function () {
            return Core.Guid.parse(XrmEx.Utility.getGlobalContext().userSettings.userId);
        };
        var getCurrentUserName = function () {
            return XrmEx.Utility.getGlobalContext().userSettings.userName;
        };
        var getCurrentUserEntityReference = function () {
            var entityReference = {};
            entityReference.id = getCurrentUserId().toString(true);
            entityReference.name = getCurrentUserName();
            entityReference.entityType = "systemuser";
            return entityReference;
        };
        var getCurrentUserRoles = function () {
            return XrmEx.Utility.getGlobalContext().userSettings.roles;;
        }
        var isCurrentUserRoleNames = function (roleNames) {
            roleNames = Core.Type.isArray(roleNames) ? roleNames : [];
            var currentUserroles = getCurrentUserRoles();
            for (var i = 0; i < currentUserroles.getAll().length; i++) {
                for (var j = 0; j < roleNames.length; j++) {
                    if (currentUserroles.get(i).name == roleNames[j])
                        return true;
                }
            }
            return false;
        }

        /**
        * 获取当前用户信息
        */
        var getCurrentUserInfo = function () {

            var result = {};
            result.userEntityReference = getCurrentUserEntityReference();
            var fb = new DynaHx.Da.FetchXmlBuilder();
            fb.select("mcs_dealer").from("systemuser");
            fb.filter();
            fb.condition("systemuserid", "eq-userid");
            fb.filterEnd();
            fb.link("mcs_dealer", "mcs_dealerid", "mcs_dealer", "der", "outer");
            fb.select("mcs_isparentcompany");
            fb.linkEnd();
            DynaHx.Da.retrieveFromFetchxml("systemuser", fb.toString(), {
                isAsync: false,
                successCallback: function (successCallbackParames) {
                    //要导出的属性
                    var dealerEntityReference = successCallbackParames.data[0].getLookUp("mcs_dealer");
                    if (dealerEntityReference != null) {
                        result.dealerEntityReference = dealerEntityReference;
                    }
                    var isparentcompany = successCallbackParames.data[0].getBool("der.mcs_isparentcompany"); //是否母公司
                    if (isparentcompany != null) {
                        result.isparentcompany = isparentcompany;
                    }
                }
            });
            return result;
        };

        /**
        * 获取当前人员信息
        */
        var getCurrentStaffInfo = function () {

            var result = {};
            result.userEntityReference = getCurrentUserEntityReference();
            var fb = new DynaHx.Da.FetchXmlBuilder();
            fb.select("mcs_useraccountid").from("mcs_useraccount");
            fb.filter("and");
            fb.condition("mcs_systemuser", "eq-userid");
            fb.condition("statecode", "=", 0).condition("mcs_entrystatusn", "=", 20);
            fb.filterEnd();
            DynaHx.Da.retrieveFromFetchxml("mcs_useraccount", fb.toString(), {
                isAsync: false,
                successCallback: function (successCallbackParames) {
                    //要导出的属性
                    var id = successCallbackParames.data[0].getString("mcs_useraccountid");
                    if (id != null) {
                        result = id;
                    }
                }
            });
            return result;
        };

        /**
         * 获取系统配置实体的值
         * @param {string} key 配置实体的Key
         */
        var getConfigValue = function (key) {
            var fb = new DynaHx.Da.FetchXmlBuilder();
            fb.select("mcs_val").from("mcs_cepconfig");
            fb.filter("and");
            fb.condition("mcs_name", "=", key)
            fb.filterEnd();
            var result = "";
            Da.retrieveFromFetchxml("mcs_cepconfig", fb.toString(), {
                isAsync: false,
                successCallback: function (successCallbackParames) {
                    if (successCallbackParames.data.length > 0) {
                        result = successCallbackParames.data[0].getString("mcs_val");
                    }
                }
            });
            return result;
        };

        /**
 * 获取SystemConfiguration配置实体的值
 * @param {string} key 配置实体的Name
 */
        var getSystemConfigurationValue = function (key) {
            var fb = new DynaHx.Da.FetchXmlBuilder();
            fb.select("ms_content").from("ms_systemconfiguration");
            fb.filter("and");
            fb.condition("ms_name", "=", key)
            fb.filterEnd();
            var result = "";
            Da.retrieveFromFetchxml("ms_systemconfiguration", fb.toString(), {
                isAsync: false,
                successCallback: function (successCallbackParames) {
                    if (successCallbackParames.data.length > 0) {
                        result = successCallbackParames.data[0].getString("ms_content");
                    }
                }
            });
            return result;
        };

        /**
         * 判断当前登录用户是否具有指定按钮的权限
         * @param {string} buttonid 按钮的id
         */
        var isCurrentUserRoleHasButton = function (buttonid) {
            //var roles = Xrm.Page.context.getUserRoles();
            var isAdmin = false;
            var roles = XrmEx.Utility.getGlobalContext().userSettings.roles;
            var fb = new DynaHx.Da.FetchXmlBuilder();
            fb.select(["mcs_rolebuttonrelationid", "mcs_rolename"]).from("mcs_rolebuttonrelation");
            fb.filter("and");
            fb.condition("statecode", "=", 0).condition("mcs_buttonid", "=", buttonid);
            fb.filter("or");
            var rolesMap = new Core.Map();
            roles.forEach(function (item) {
                //fb.condition("mcs_rolename", "=", item.name);
                rolesMap.add(item.name, item);
                if (item.name === "系统管理员" || item.name === "System Administrator") {
                    isAdmin = true;
                    return;
                }
            });
            fb.filterEnd();
            fb.filterEnd();

            if (isAdmin)
                return true;

            var result = false;
            Da.retrieveFromFetchxml("mcs_rolebuttonrelation", fb.toString(), {
                isAsync: false,
                successCallback: function (successCallbackParames) {
                    successCallbackParames.data.forEach(function (entity) {
                        if (rolesMap.has(entity.getString("mcs_rolename"))) {
                            result = true;
                        }
                    });
                    //if (successCallbackParames.data.length > 0) {
                    //    result = true;
                    //}
                }
            });
            return result;
        };


        /**
         * 获取本地化字典资源中的值
         * @param {string} resourcePath 本地化字典资源的路径
         * @param {string} resourceKey  本地化字典资源的键
         * @param {array} args  要替换的字符串数组
         */
        var getResourceString = function (resourcePath, resourceKey, args) {
            try {
                var val = XrmEx.Utility.getResourceString({ resourcePath: resourcePath, resourceKey: resourceKey });
                if (Core.Type.isNullOrEmpty(val))
                    return "";
                var sb = new Core.StringBuilder();
                sb.append(val, args);
                return sb.toString();
            } catch (e) {
                return "";
            }
        };

        /**
         * 打开一个消息提示的对话框
         * @param {string} text 消息内容
         * @param {object} optionParames   可选参数
         * @param {string} optionParames.title 对话框标题 默认为消息提醒
         * @param {object} optionParames.width 对话框的宽 可接收number类型或者百分比{value: 80, unit:"%"}
         * @param {object} optionParames.height 对话框的高 可接收number类型或者百分比{value: 80, unit:"%"}
         * @param {string} optionParames.confirmButtonLabel 对话框确定按钮的文字
         * @param {function} optionParames.successCallback 对话框点击确定后的事件
         * @param {function} optionParames.errorsCallback 对话框打开失败后的事件
         */
        var openAlertDialog = function (text, optionParames) {

            optionParames = Core.Type.isObject(optionParames) ? optionParames : {};
            optionParames.title = !Core.Type.isNullOrEmpty(optionParames.title) ? optionParames.title : getResourceString(getResourceUrl(), "messageTitle"); // "消息提示"
            optionParames.width = !Core.Type.isNull(optionParames.width) ? optionParames.width : 260;
            optionParames.height = !Core.Type.isNull(optionParames.height) ? optionParames.height : 120;
            optionParames.confirmButtonLabel = !Core.Type.isNull(optionParames.confirmButtonLabel) ? optionParames.confirmButtonLabel : getResourceString(getResourceUrl(), "confirm");//"确定"
            optionParames.successCallback = Core.Type.isFunction(optionParames.successCallback) ? optionParames.successCallback : null;
            optionParames.errorsCallback = Core.Type.isFunction(optionParames.errorsCallback) ? optionParames.errorsCallback : null;
            var parames = {
                alertStrings: { confirmButtonLabel: optionParames.confirmButtonLabel, text: text, title: optionParames.title },
                alertOptions: { height: optionParames.height, width: optionParames.width },
                successCallback: optionParames.successCallback,
                errorsCallback: optionParames.errorsCallback
            };
            XrmEx.Navigation.openAlertDialog(parames);
        };


        /**
         * 打开一个消息提示的对话框WebSource方式打开
         * @param {string} text 消息内容
         * @param {object} optionParames   可选参数
         * @param {string} optionParames.title 对话框标题 默认为消息提醒
         * @param {number} optionParames.width 对话框的宽 
         * @param {number} optionParames.height 对话框的高
         * @param {string} optionParames.confirmButtonLabel 对话框确定按钮的文字
         * @param {function} optionParames.successCallback 对话框点击确定后的事件
         * @param {function} optionParames.errorsCallback 对话框打开失败后的事件
         * @param {boolean} optionParames.autoHeight 是否启动自动计算高度
         * @param {number} optionParames.autoHeightPx 自动计算高度的计算量 默认为17
         */
        var openAlertDialogFromWebSource = function (content, optionParames) {
            content = !Core.Type.isNullOrEmpty(content) ? content : "";
            optionParames = Core.Type.isObject(optionParames) ? optionParames : {};
            optionParames.title = !Core.Type.isNullOrEmpty(optionParames.title) ? optionParames.title : getResourceString(getResourceUrl(), "messageTitle"); // "消息提示"
            optionParames.width = !Core.Type.isNull(optionParames.width) ? optionParames.width : 260;
            optionParames.height = !Core.Type.isNull(optionParames.height) ? optionParames.height : 220;
            optionParames.confirmButtonLabel = !Core.Type.isNull(optionParames.confirmButtonLabel) ? optionParames.confirmButtonLabel : getResourceString(getResourceUrl(), "confirm");//"确定"
            optionParames.successCallback = Core.Type.isFunction(optionParames.successCallback) ? optionParames.successCallback : null;
            optionParames.errorsCallback = Core.Type.isFunction(optionParames.errorsCallback) ? optionParames.errorsCallback : null;
            optionParames.autoHeight = Core.Type.isBoolean(optionParames.autoHeight) ? optionParames.autoHeight : false;
            optionParames.autoHeightPx = !Core.Type.isNull(optionParames.autoHeightPx) ? optionParames.autoHeightPx : 17;

            if (optionParames.autoHeight) {  //自动计算高度
                var match = content.match(new RegExp(/<li/, "g"));
                var len = (match ? match.length : 0)
                match = content.match(new RegExp(/<br/, "g"));
                len += (match ? match.length : 0)
                optionParames.height = len * optionParames.autoHeightPx + 180;
                optionParames.height = (optionParames.height < 220 ? 220 : optionParames.height);
                console.log(optionParames.height);
            }

            var args = {
                title: optionParames.title,
                confirmButtonLabel: optionParames.confirmButtonLabel,
                content: content
            };

            navigateToWebResource("mcs_/Module/DynaHx/Html/DialogAlert.html", {
                width: optionParames.width,
                height: optionParames.height,
                arguments: args,
                hideDialogHeader: true,
                successCallback: optionParames.successCallback,
                errorsCallback: optionParames.errorsCallback,
            });
        };


        /**
         * 打开一个错误提示的对话框
         * @param {string} message 错误提示内容
         * @param {object} optionParames   可选参数
         * @param {number} optionParames.errorCode 错误提示编码
         * @param {number} optionParames.details 提供一个可以下载的错误提示文本
         */
        var openErrorDialog = function (message, optionParames) {
            optionParames = Core.Type.isObject(optionParames) ? optionParames : {};
            optionParames.errorCode = !Core.Type.isNull(optionParames.errorCode) ? optionParames.errorCode : 0;
            optionParames.details = !Core.Type.isNull(optionParames.details) ? optionParames.details : "";
            var errorOptions = {
                message: message,
                errorCode: optionParames.errorCode
            };
            if (!Core.Type.isNullOrEmpty(errorOptions.details)) {
                errorOptions.details = details;
            }
            var parames = {
                errorOptions: errorOptions
            };
            XrmEx.Navigation.openErrorDialog(parames);
        };

        /**
         * 打开一个确认的对话框
         * @param {string} text 消息内容
         * @param {object} optionParames   可选参数
         * @param {string} optionParames.title 对话框标题 默认为消息提醒
         * @param {object} optionParames.width 对话框的宽 可接收number类型或者百分比{value: 80, unit:"%"}
         * @param {object} optionParames.height 对话框的高 可接收number类型或者百分比{value: 80, unit:"%"}
         * @param {function} optionParames.confirmCallback 对话框点击确定后的事件
         * @param {function} optionParames.cancelCallback 对话框点击取消后的事件
         * @param {string} optionParames.confirmButtonLabel 确定的按钮的标签
         * @param {string} optionParames.cancelButtonLabel 取消按钮的标签
         * @param {string} optionParames.subtitle 对话框中显示的字幕
         */
        var openConfirmDialog = function (text, optionParames) {
            optionParames = Core.Type.isObject(optionParames) ? optionParames : {};
            optionParames.title = !Core.Type.isNullOrEmpty(optionParames.title) ? optionParames.title : getResourceString(getResourceUrl(), "messageTitle"); // "消息提示"
            optionParames.width = !Core.Type.isNull(optionParames.width) ? optionParames.width : 450;
            optionParames.height = !Core.Type.isNull(optionParames.height) ? optionParames.height : 200;
            optionParames.confirmCallback = Core.Type.isFunction(optionParames.confirmCallback) ? optionParames.confirmCallback : null;
            optionParames.cancelCallback = Core.Type.isFunction(optionParames.cancelCallback) ? optionParames.cancelCallback : null;
            optionParames.confirmButtonLabel = !Core.Type.isNullOrEmpty(optionParames.confirmButtonLabel) ? optionParames.confirmButtonLabel : getResourceString(getResourceUrl(), "confirm");//"确定"
            optionParames.cancelButtonLabel = !Core.Type.isNullOrEmpty(optionParames.cancelButtonLabel) ? optionParames.cancelButtonLabel : getResourceString(getResourceUrl(), "cancel"); //"取消"
            optionParames.subtitle = !Core.Type.isNullOrEmpty(optionParames.subtitle) ? optionParames.subtitle : "";


            var parames = {
                confirmStrings: { text: text, title: optionParames.title, subtitle: optionParames.subtitle, confirmButtonLabel: optionParames.confirmButtonLabel, cancelButtonLabel: optionParames.cancelButtonLabel },
                confirmOptions: { height: optionParames.height, width: optionParames.width },
                confirmCallback: optionParames.confirmCallback,
                cancelCallback: optionParames.cancelCallback
            };
            XrmEx.Navigation.openConfirmDialog(parames);
        };


        /**
         * 导航到一个WebResource
         * @param {string} webresourceName WebResource名称
         * @param {object} optionParames   可选参数
         * @param {object} optionParames.width 对话框的宽 可接收number类型或者百分比{value: 100, unit:"%"}
         * @param {object} optionParames.height 对话框的高 可接收number类型或者百分比{value: 100, unit:"%"}
         * @param {string} optionParames.data 使用get方式传输的字符串 ?data=xxxx
         * @param {number} optionParames.target 打开的方式 1内联的方式打开 2模式窗口的方式打开(默认)
         * @param {number} optionParames.position 打开的位置 1在中央打开(默认) 2在侧面打开
         * @param {object} optionParames.arguments 传输的参数 先注册然后使用
         * @param {number} optionParames.title 窗体的title 此方式并不完美 建议还是留空 修改WebResource的名称做为Title
         * @param {function} optionParames.successCallback 关闭后的回调事件
         * @param {function} optionParames.errorsCallback 打开失败后的回调事件
         * @param {boolean} optionParames.hideDialogHeader 是否隐藏头部
         */
        var navigateToWebResource = function (webresourceName, optionParames) {
            optionParames = Core.Type.isObject(optionParames) ? optionParames : {};
            optionParames.width = !Core.Type.isNull(optionParames.width) ? optionParames.width : { value: 100, unit: "%" };
            optionParames.height = !Core.Type.isNull(optionParames.height) ? optionParames.height : { value: 100, unit: "%" };
            optionParames.target = optionParames.target === 1 || optionParames.target === 2 ? optionParames.target : 2;
            optionParames.position = optionParames.position === 1 || optionParames.position === 2 ? optionParames.target : 1;
            optionParames.hideDialogHeader = Core.Type.isBoolean(optionParames.hideDialogHeader) ? optionParames.hideDialogHeader : false;
            optionParames.data = !Core.Type.isNullOrEmpty(optionParames.data) ? optionParames.data : "";
            optionParames.successCallback = Core.Type.isFunction(optionParames.successCallback) ? optionParames.successCallback : function () { };
            optionParames.errorsCallback = Core.Type.isFunction(optionParames.errorsCallback) ? optionParames.errorsCallback : function () { };

            Core.ShareData.set("navigateArguments", optionParames.arguments);

            var parames = {
                pageInput: {
                    pageType: "webresource",
                    webresourceName: webresourceName,
                    data: optionParames.data
                },
                navigationOptions: {
                    target: optionParames.target,
                    width: optionParames.width,
                    height: optionParames.height,
                    position: optionParames.position,
                    hideDialogHeader: optionParames.hideDialogHeader
                },
                successCallback: function () {
                    if (Core.ShareData.has("navigateReturnValue")) {
                        optionParames.successCallback(Core.ShareData.get("navigateReturnValue"));
                    }
                    else {
                        optionParames.successCallback();
                    }
                },
                errorsCallback: optionParames.errorsCallback
            };

            if (!Core.Type.isNullOrEmpty(optionParames.title)) {
                var timeRunMillisecond = 0;
                var interval = null;
                var changeWindowListening = function () {
                    console.log(timeRunMillisecond);
                    if (window.top.document.getElementById("defaultDialogChromeTitle") != null) {
                        window.top.document.getElementById("defaultDialogChromeTitle").innerText = optionParames.title;
                        window.clearInterval(interval);
                    }

                    timeRunMillisecond += 200;
                    if (timeRunMillisecond > 2000) {
                        window.clearInterval(interval);
                    }
                };
                interval = window.setInterval(changeWindowListening, 200);
            }
            XrmEx.Navigation.navigateTo(parames);
        };

        var getNavigateArguments = function () {
            if (DynaHx.Core.ShareData.has("navigateArguments")) {
                return DynaHx.Core.ShareData.get("navigateArguments");
            }
            return null;
        };

        var getNavigateArgument = function (name) {
            var args = getNavigateArguments();
            if (!Core.Type.isNull(args))
                return args[name];
            return null;
        };

        var closeNavigate = function (returnValue) {
            //var parantDynaHx = Core.Base.findFrameDynaHx();
            //if (!Core.Type.isNullOrEmpty(returnValue)) {
            //    parantDynaHx.Core.ShareData.set("navigateReturnValue", returnValue);
            //}
            //else {
            //    if (parantDynaHx.Core.ShareData.has("navigateReturnValue")) {
            //        parantDynaHx.Core.ShareData.remove("navigateReturnValue");
            //    }
            //}
            //parent.$("button[data-id='dialogCloseIconButton']", parent.document).click();

            if (!Core.Type.isNullOrEmpty(returnValue)) {
                DynaHx.Core.ShareData.set("navigateReturnValue", returnValue);
            }
            else {
                if (DynaHx.Core.ShareData.has("navigateReturnValue")) {
                    DynaHx.Core.ShareData.remove("navigateReturnValue");
                }
            }
            var dialogClose = parent.$("button[data-id='dialogCloseIconButton']", parent.document);
            if (dialogClose.length > 0) {
                //dialogClose[dialogClose.length - 1].click();
                var closeButton = null;
                for (var i = 0; i < dialogClose.length; i++) {
                    if (!Core.Type.isNull(dialogClose[i].id) && dialogClose[i].id.indexOf("defaultDialogChromeCloseIconButton") != -1) {
                        closeButton = dialogClose[i];
                    }
                }

                if (!Core.Type.isNull(closeButton))
                    closeButton.click();
            }

            //parent.$("button[data-id='dialogCloseIconButton']", parent.document)[0].click();
        };

        var navigateToFormNew = function (entityName, formParameters, optionParames) {
            formParameters = Core.Type.isObject(formParameters) ? formParameters : {};
            optionParames = Core.Type.isObject(optionParames) ? optionParames : {};
            optionParames.width = !Core.Type.isNull(optionParames.width) ? optionParames.width : { value: 100, unit: "%" };
            optionParames.height = !Core.Type.isNull(optionParames.height) ? optionParames.height : { value: 100, unit: "%" };
            optionParames.position = optionParames.position === 1 || optionParames.position === 2 ? optionParames.target : 1;
            optionParames.target = optionParames.target === 1 || optionParames.target === 2 ? optionParames.target : 2;
            optionParames.hideDialogHeader = Core.Type.isBoolean(optionParames.hideDialogHeader) ? optionParames.hideDialogHeader : false;
            optionParames.successCallback = Core.Type.isFunction(optionParames.successCallback) ? optionParames.successCallback : null;
            optionParames.errorsCallback = Core.Type.isFunction(optionParames.errorsCallback) ? optionParames.errorsCallback : null;

            var parames = {
                pageInput: {
                    pageType: "entityrecord",
                    entityName: entityName,
                    data: formParameters
                },
                navigationOptions: {
                    target: optionParames.target,
                    width: optionParames.width,
                    height: optionParames.height,
                    position: optionParames.position,
                    hideDialogHeader: optionParames.hideDialogHeader
                },
                successCallback: optionParames.successCallback,
                errorsCallback: optionParames.errorsCallback
            };
            XrmEx.Navigation.navigateTo(parames);
        };

        var navigateToForm = function (entityName, entityId, optionParames) {

            optionParames = Core.Type.isObject(optionParames) ? optionParames : {};
            optionParames.width = !Core.Type.isNull(optionParames.width) ? optionParames.width : { value: 100, unit: "%" };
            optionParames.height = !Core.Type.isNull(optionParames.height) ? optionParames.height : { value: 100, unit: "%" };
            optionParames.position = optionParames.position === 1 || optionParames.position === 2 ? optionParames.target : 1;
            optionParames.target = optionParames.target === 1 || optionParames.target === 2 ? optionParames.target : 2;
            optionParames.hideDialogHeader = Core.Type.isBoolean(optionParames.hideDialogHeader) ? optionParames.hideDialogHeader : false;
            optionParames.successCallback = Core.Type.isFunction(optionParames.successCallback) ? optionParames.successCallback : null;
            optionParames.errorsCallback = Core.Type.isFunction(optionParames.errorsCallback) ? optionParames.errorsCallback : null;

            var parames = {
                pageInput: {
                    pageType: "entityrecord",
                    entityName: entityName,
                    entityId: entityId
                },
                navigationOptions: {
                    target: optionParames.target,
                    width: optionParames.width,
                    height: optionParames.height,
                    position: optionParames.position,
                    hideDialogHeader: optionParames.hideDialogHeader
                },
                successCallback: optionParames.successCallback,
                errorsCallback: optionParames.errorsCallback
            };
            XrmEx.Navigation.navigateTo(parames);
        };

        var navigateToList = function (entityName) {
            var parames = {
                pageInput: {
                    pageType: "entitylist",
                    entityName: entityName
                }
            };
            XrmEx.Navigation.navigateTo(parames);
        }

        /**
        @typedef navigateToApprovalSuccessCallbackReturnValue
        @type {Object}
        @property {number} code 1、表示审批通过 2、表示审批拒绝.
        @property {string} name 审批的文本内容.
        @property {string} comments 审批的意见.
        */

        /**
        * @callback navigateToApprovalSuccessCallback
        * @param {navigateToApprovalSuccessCallbackReturnValue} retutnValue  回调函数的参数
        */

        /**
         * 导航到一个审批的对话框
         * @param {object} optionParames   可选参数
         * @param {Array} optionParames.approvalStatusArray 审批的项目 默认为[{ code: 1, name: "审批通过" }, { code: 2, name: "审批拒绝" }]
         * @param {object} optionParames.width 对话框的宽 可接收number类型或者百分比{value: 100, unit:"%"}
         * @param {object} optionParames.height 对话框的高 可接收number类型或者百分比{value: 100, unit:"%"}
         * @param {navigateToApprovalSuccessCallback} optionParames.successCallback 关闭后的回调事件
         * @param {function} optionParames.errorsCallback 打开失败后的回调事件
         */
        var navigateToApproval = function (optionParames) {
            optionParames = Core.Type.isObject(optionParames) ? optionParames : {};
            optionParames.width = !Core.Type.isNull(optionParames.width) ? optionParames.width : 450;
            optionParames.height = !Core.Type.isNull(optionParames.height) ? optionParames.height : 320;
            optionParames.dialogHeader = !Core.Type.isNullOrEmpty(optionParames.dialogHeader) ? optionParames.dialogHeader : getResourceString(getResourceUrl(), "approvaDialogHeader");
            optionParames.dialogHeaderDesc = !Core.Type.isNullOrEmpty(optionParames.dialogHeaderDesc) ? optionParames.dialogHeaderDesc : getResourceString(getResourceUrl(), "approvaDialogHeaderDesc");
            optionParames.approvalStatusLabel = !Core.Type.isNullOrEmpty(optionParames.approvalStatusLabel) ? optionParames.approvalStatusLabel : getResourceString(getResourceUrl(), "approvalStatusLabel");
            optionParames.approvalStatusArray = Core.Type.isArray(optionParames.approvalStatusArray) ? optionParames.approvalStatusArray : [{ code: 1, name: getResourceString(getResourceUrl(), "approvalStatusOption1") }, { code: 2, name: getResourceString(getResourceUrl(), "approvalStatusOption2") }];
            optionParames.approvalCommentsLabel = !Core.Type.isNullOrEmpty(optionParames.approvalCommentsLabel) ? optionParames.approvalCommentsLabel : getResourceString(getResourceUrl(), "approvalCommentsLabel");
            optionParames.confirmButtonLabel = !Core.Type.isNullOrEmpty(optionParames.confirmButtonLabel) ? optionParames.confirmButtonLabel : getResourceString(getResourceUrl(), "confirm");//"确定"
            optionParames.cancelButtonLabel = !Core.Type.isNullOrEmpty(optionParames.cancelButtonLabel) ? optionParames.cancelButtonLabel : getResourceString(getResourceUrl(), "cancel"); //"取消"

            navigateToWebResource("mcs_/Module/DynaHx/Html/Approval.html", {
                width: optionParames.width,
                height: optionParames.height,
                hideDialogHeader: true,
                arguments: {
                    dialogHeader: optionParames.dialogHeader,
                    dialogHeaderDesc: optionParames.dialogHeaderDesc,
                    approvalStatusLabel: optionParames.approvalStatusLabel,
                    approvalStatusArray: optionParames.approvalStatusArray,
                    approvalCommentsLabel: optionParames.approvalCommentsLabel,
                    confirmButtonLabel: optionParames.confirmButtonLabel,
                    cancelButtonLabel: optionParames.cancelButtonLabel,
                },
                hideDialogHeader: true,
                successCallback: function (returnValue) {
                    if (!Core.Type.isNull(returnValue)) {
                        optionParames.successCallback(returnValue);
                    }
                },
                errorsCallback: optionParames.errorsCallback,
            });
        };


        /**
        * 导航到一个注释预览的对话框
        */
        var navigateToAnnotationPreview = function (entityName, entityId) {
            navigateToWebResource("mcs_/Module/DynaHx/Html/AnnotationPreview.html", {
                width: 780,
                height: 800,
                hideDialogHeader: true,
                arguments: {
                    entityName: entityName,
                    entityId: entityId,
                },
                hideDialogHeader: true,
                successCallback: function (returnValue) {

                },
                errorsCallback: function () {

                }
            });
        };


        /**
         * 显示带有指定消息的进度对话框 进度对话框将阻塞UI，直到使用closeProgressIndicator方法将其关闭。因此，必须谨慎使用此方法
         * @param {string} message   消息内容
         */
        var showProgressIndicator = function (message) {
            XrmEx.Utility.showProgressIndicator({ message: message });
        };
        /**
         * 关闭进度对话框
         * @param {string} message   消息内容
         */
        var closeProgressIndicator = function () {
            XrmEx.Utility.closeProgressIndicator();
        };


        /**
         * 打开一个模式对话框(此方法为未公开的函数请谨慎使用)
         * @param {string} webresourceName webresource的名称
         * @param {object} optionParames   可选参数
         * @param {object} optionParames.width 对话框的宽 可接收number
         * @param {object} optionParames.height 对话框的高 可接收number
         * @param {number} optionParames.dialogArguments 模式窗口的传输的参数
         * @param {function} optionParames.initFunctionName 初始化方法名
         * @param {function} optionParames.returnFunction 返回的方法
         */
        var openDialogWebresource = function (webresourceName, optionParames) {
            var url = XrmEx.Utility.getWebResourceUrl({ webresourceName: webresourceName });
            if (Core.Type.isNullOrEmpty(url)) {
                throw new Error("webresource名称无效");
            }
            openDialogUrl(url, optionParames);
        };


        var openDialogUrl = function (url, optionParames) {
            optionParames = Core.Type.isObject(optionParames) ? optionParames : {};
            optionParames.width = !Core.Type.isNull(optionParames.width) ? optionParames.width : { value: 100, unit: "%" };
            optionParames.height = !Core.Type.isNull(optionParames.height) ? optionParames.height : { value: 100, unit: "%" };
            optionParames.position = optionParames.position === 1 || optionParames.position === 2 ? optionParames.target : 2;
            optionParames.dialogArguments = Core.Type.isObject(optionParames.dialogArguments) ? optionParames.dialogArguments : null;
            optionParames.initFunctionName = Core.Type.isFunction(optionParames.initFunctionName) ? optionParames.initFunctionName : null;
            optionParames.returnFunction = Core.Type.isFunction(optionParames.returnFunction) ? optionParames.returnFunction : null;

            if (Core.Type.isObject(optionParames.width) && Core.Type.isNumber(optionParames.width.value) && optionParames.width.unit === "%") {
                optionParames.width = optionParames.width.value / 100 * window.top.document.documentElement.clientWidth;
            }
            if (Core.Type.isObject(optionParames.height) && Core.Type.isNumber(optionParames.height.value) && optionParames.height.unit === "%") {
                optionParames.height = optionParames.height.value / 100 * window.top.document.documentElement.clientHeight;
            }


            var parames = {
                url: url,
                options: {
                    height: optionParames.height,
                    position: optionParames.position,
                    width: optionParames.width
                },
                dialogArguments: optionParames.dialogArguments,
                initFunctionName: optionParames.initFunctionName,
                returnFunction: optionParames.returnFunction
            };
            XrmEx.Internal.openLegacyWebDialog(parames);

        };


        var openFormNew = function (entityName, formParameters) {
            formParameters = Core.Type.isObject(formParameters) ? formParameters : {};
            var entityFormOptions = {};
            entityFormOptions["entityName"] = entityName;

            var parames = {
                entityFormOptions: entityFormOptions,
                formParameters: formParameters
            };
            XrmEx.Navigation.openForm(parames);
        };

        var openForm = function (entityName, entityId) {
            var entityFormOptions = {};
            entityFormOptions["entityName"] = entityName;
            entityFormOptions["entityId"] = entityId;
            var parames = {
                entityFormOptions: entityFormOptions,
            };
            XrmEx.Navigation.openForm(parames);
        };
        /**
         * 打开一条件选择的模式窗口
         * @param {string} entityLogicalName 打开的实体名称
         * @param {object} optionParames   可选参数
         * @param {string} optionParames.sFetchXml 默认选择的条件
         * @param {function} optionParames.successCallback 回调的方法
         */
        var openDialogSetFilters = function (entityLogicalName, optionParames) {
            optionParames = Core.Type.isObject(optionParames) ? optionParames : {};
            var parames = {
                entityLogicalName: entityLogicalName,
                successCallback: function (successCallback) {
                    var etc = successCallback.ObjectTypeCode;
                    var url = XrmEx.Utility.getGlobalContext().getClientUrl() + "/Tools/ViewEditor/Dialogs/SetFilters.aspx?entityCode=" + etc + "&dType=1";
                    var dialogArguments = {};
                    dialogArguments.sFetchXml = optionParames.sFetchXml;
                    openDialogUrl(url, {
                        width: 600,
                        height: 600,
                        dialogArguments: dialogArguments,
                        returnFunction: optionParames.successCallback
                    });
                },
                errorCallback: function (errorCallback) {

                }
            }
            XrmEx.Utility.getEntityMetadata(parames);
        };

        var getEntityMetadata = function (entityLogicalName, optionParames) {
            optionParames = Core.Type.isObject(optionParames) ? optionParames : {};
            optionParames.attributes = Core.Type.isArray(optionParames.attributes) ? optionParames.attributes : [];
            optionParames.successCallback = Core.Type.isFunction(optionParames.successCallback) ? optionParames.successCallback : function () { };
            optionParames.errorsCallback = Core.Type.isFunction(optionParames.errorsCallback) ? optionParames.errorsCallback : function () { };
            var parames = {
                entityLogicalName: entityLogicalName,
                attributes: optionParames.attributes,
                successCallback: function (successParames) {
                    optionParames.successCallback(successParames);
                },
                errorCallback: function (errorParames) {
                    optionParames.successCallback(errorParames);
                }
            }
            XrmEx.Utility.getEntityMetadata(parames);
        };



        var getPageArgument = function (name) {
            var query = window.location.search.substring(1);
            var vars = query.split("&");
            for (var i = 0; i < vars.length; i++) {
                var pair = vars[i].split("=");
                if (pair[0] == name) {
                    return decodeURIComponent(pair[1]);
                }
            }
            return null;
        };

        /**
        * 打开一LookUp选择器
        * @param {string} entityLogicalName 打开的实体名称
        * @param {object} optionParames   可选参数
        * @param {boolean} optionParames.allowMultiSelect 是否打开多选
        * @param {string} optionParames.searchText 默认的搜索文本
        * @param {string} optionParames.filterXml 过滤的条件 <filter type='or'><condition attribute='name' operator='like' value='A%' /></filter>
        * @param {function} optionParames.successCallback 回调的方法
        */
        var lookupObjects = function (entityLogicalName, optionParames) {
            optionParames = Core.Type.isObject(optionParames) ? optionParames : {};
            optionParames.searchText = Core.Type.isNullOrEmpty(optionParames.searchText) ? optionParames.searchText : "";
            optionParames.filterXml = Core.Type.isNullOrEmpty(optionParames.filterXml) ? optionParames.filterXml : "";
            optionParames.allowMultiSelect = Core.Type.isBoolean(optionParames.allowMultiSelect) ? optionParames.allowMultiSelect : false;
            optionParames.successCallback = Core.Type.isFunction(optionParames.successCallback) ? optionParames.successCallback : function () { };
            optionParames.errorsCallback = Core.Type.isFunction(optionParames.errorsCallback) ? optionParames.errorsCallback : function () { };

            var lookupOptions =
            {
                allowMultiSelect: optionParames.allowMultiSelect,
                defaultEntityType: entityLogicalName,
                entityTypes: [entityLogicalName],
                defaultViewId: "",
                viewIds: [],
                searchText: optionParames.searchText,
                filters: [{ filterXml: optionParames.filterXml, entityLogicalName: entityLogicalName }]
            };

            var parames = {};
            parames.lookupOptions = lookupOptions;
            parames.successCallback = optionParames.successCallback;
            parames.errorParames = optionParames.errorCallback;

            XrmEx.Utility.lookupObjects(parames);

        };


        /**
        * 打开一个WebResource
        * @param {string} entityLogicalName 打开的实体名称
        * @param {object} optionParames   可选参数
        * @param {boolean} optionParames.allowMultiSelect 是否打开多选
        * @param {string} optionParames.searchText 默认的搜索文本
        */
        var openWebResource = function (webResourceName) {
            var parames = {};
            var windowOptions = {};
            //windowOptions.width = 100;
            //windowOptions.height = 100;
            //parames.windowOptions = windowOptions;

            parames.webResourceName = webResourceName;
            XrmEx.Navigation.openWebResource(parames);
        }

        return {
            getResourceString: getResourceString,
            openAlertDialog: openAlertDialog,
            openAlertDialogFromWebSource: openAlertDialogFromWebSource,
            openErrorDialog: openErrorDialog,
            openConfirmDialog: openConfirmDialog,
            navigateToWebResource: navigateToWebResource,
            navigateToFormNew: navigateToFormNew,
            navigateToForm: navigateToForm,
            navigateToList: navigateToList,
            navigateToApproval: navigateToApproval,
            navigateToAnnotationPreview: navigateToAnnotationPreview,
            getNavigateArguments: getNavigateArguments,
            getNavigateArgument: getNavigateArgument,
            showProgressIndicator: showProgressIndicator,
            closeProgressIndicator: closeProgressIndicator,
            openDialogWebresource: openDialogWebresource,
            openDialogUrl: openDialogUrl,
            isCurrentUserRoleHasButton: isCurrentUserRoleHasButton,
            isCurrentUserRoleNames: isCurrentUserRoleNames,
            getLanguageId: getLanguageId,
            closeNavigate: closeNavigate,
            openFormNew: openFormNew,
            openForm: openForm,
            getConfigValue: getConfigValue,
            getSystemConfigurationValue: getSystemConfigurationValue,
            openDialogSetFilters: openDialogSetFilters,
            getCurrentUserId: getCurrentUserId,
            getCurrentUserName: getCurrentUserName,
            getCurrentUserEntityReference: getCurrentUserEntityReference,
            getCurrentUserInfo: getCurrentUserInfo,
            getCurrentStaffInfo: getCurrentStaffInfo,
            getCurrentUserRoles: getCurrentUserRoles,
            getEntityMetadata: getEntityMetadata,
            getPageArgument: getPageArgument,
            lookupObjects: lookupObjects,
            openWebResource: openWebResource
        };

    }());

    var XrmEx = (function () {

        var Utility, Navigation, Dialog, Internal, WebApi;

        var Base = (function () {
            var findFrmameXrmNamespace = function (namespac) {
                for (var i = 0; i < window.top.frames.length; i++) {
                    try {
                        if (!Core.Type.isNull(window.top.frames[i].DynaHx) && !Core.Type.isNullOrEmpty(window.top.frames[i].Xrm) && !Core.Type.isNullOrEmpty(window.top.frames[i].Xrm[namespac])) {
                            return window.top.frames[i].Xrm[namespac];
                        }
                    } catch (ex) {
                    }
                }
                if (!Core.Type.isNull(window.top.Xrm) && !Core.Type.isNull(window.top.Xrm[namespac]))
                    return window.top.Xrm[namespac];
                return null;
            };
            var getXrmNamespace = function (namespac) {
                if (Core.Type.isNull(window.Xrm) || Core.Type.isNull(Xrm[namespac])) {
                    return findFrmameXrmNamespace(namespac);
                }
                else {
                    return Xrm[namespac];
                }
                ;
            };
            return {
                findFrmameXrmNamespace: findFrmameXrmNamespace,
                getXrmNamespace: getXrmNamespace
            };
        }());
        Utility = (function () {
            var getGlobalContext, getResourceString, showProgressIndicator, closeProgressIndicator, getWebResourceUrl, getEntityMetadata, lookupObjects;
            getGlobalContext = function () {

                var utility = Base.getXrmNamespace("Utility");
                return utility.getGlobalContext();
            };
            getResourceString = function (parames) {
                var utility = Base.getXrmNamespace("Utility");
                return utility.getResourceString(parames.resourcePath, parames.resourceKey);
            };

            getWebResourceUrl = function (parames) {
                return getGlobalContext().getWebResourceUrl(parames.webresourceName);
            };

            showProgressIndicator = function (parames) {
                var utility = Base.getXrmNamespace("Utility");
                utility.showProgressIndicator(parames.message);
            };
            closeProgressIndicator = function () {
                var utility = Base.getXrmNamespace("Utility");
                utility.closeProgressIndicator();
            };

            getEntityMetadata = function (parames) {
                var utility = Base.getXrmNamespace("Utility");
                utility.getEntityMetadata(parames.entityLogicalName, parames.attributes).then(
                    function (successParames) {
                        if (Core.Type.isFunction(parames.successCallback)) {
                            parames.successCallback(successParames);
                        }
                    },
                    function (errorParames) {
                        if (Core.Type.isFunction(parames.errorCallback)) {
                            parames.errorCallback(errorParames);
                        }
                    }
                );
            };

            lookupObjects = function (parames) {
                var utility = Base.getXrmNamespace("Utility");
                utility.lookupObjects(parames.lookupOptions).then(
                    function (successParames) {
                        if (Core.Type.isFunction(parames.successCallback)) {
                            parames.successCallback(successParames);
                        }
                    },
                    function (errorParames) {
                        if (Core.Type.isFunction(parames.errorCallback)) {
                            parames.errorCallback(errorParames);
                        }
                    });
            }

            return {
                getGlobalContext: getGlobalContext,
                getResourceString: getResourceString,
                showProgressIndicator: showProgressIndicator,
                closeProgressIndicator: closeProgressIndicator,
                getWebResourceUrl: getWebResourceUrl,
                getEntityMetadata: getEntityMetadata,
                lookupObjects: lookupObjects
            };
        }());
        Navigation = (function () {
            var openErrorDialog, openAlertDialog, openConfirmDialog, navigateTo, openForm, openWebResource;

            openForm = function (parames) {
                var navigation = Base.getXrmNamespace("Navigation");
                navigation.openForm(parames.entityFormOptions, parames.formParameters).then(
                    function (success) {
                        if (Core.Type.isFunction(parames.successCallback)) {
                            parames.successCallback(success);
                        }
                    },
                    function (error) {
                        if (Core.Type.isFunction(parames.errorsCallback)) {
                            parames.errorsCallback(error);
                        }
                    });
            };
            openErrorDialog = function (parames) {
                var navigation = Base.getXrmNamespace("Navigation");
                navigation.openErrorDialog(parames.errorOptions).then(
                    function (success) {
                        if (Core.Type.isFunction(parames.successCallback)) {
                            parames.successCallback(success);
                        }
                    },
                    function (error) {
                        if (Core.Type.isFunction(parames.errorsCallback)) {
                            parames.errorsCallback(error);
                        }
                    }
                );
            };
            openWebResource = function (parames) {
                var navigation = Base.getXrmNamespace("Navigation");
                navigation.openWebResource(parames.webResourceName, parames.windowOptions);
            };
            openAlertDialog = function (parames) {
                var navigation = Base.getXrmNamespace("Navigation");
                navigation.openAlertDialog(parames.alertStrings, parames.alertOptions).then(
                    function success(result) {
                        if (Core.Type.isFunction(parames.successCallback)) {
                            parames.successCallback(result);
                        }
                    },
                    function (error) {
                        if (Core.Type.isFunction(parames.errorsCallback)) {
                            parames.errorsCallback(error);
                        }
                    }
                );
            };
            openConfirmDialog = function (parames) {
                var navigation = Base.getXrmNamespace("Navigation");
                navigation.openConfirmDialog(parames.confirmStrings, parames.confirmOptions).then(
                    function (success) {
                        if (success.confirmed) {
                            if (Core.Type.isFunction(parames.confirmCallback)) {
                                parames.confirmCallback();
                            }
                        }
                        else {
                            if (Core.Type.isFunction(parames.cancelCallback)) {
                                parames.cancelCallback();
                            }
                        }
                    });
            };
            navigateTo = function (parames) {
                var navigation = Base.getXrmNamespace("Navigation");
                navigation.navigateTo(parames.pageInput, parames.navigationOptions).then(
                    function success() {
                        if (Core.Type.isFunction(parames.successCallback)) {
                            parames.successCallback();
                        }
                    },
                    function error() {
                        if (Core.Type.isFunction(parames.errorsCallback)) {
                            parames.errorsCallback();
                        }
                    }
                );
            };

            return {
                openErrorDialog: openErrorDialog,
                openAlertDialog: openAlertDialog,
                openConfirmDialog: openConfirmDialog,
                navigateTo: navigateTo,
                openForm: openForm,
                openWebResource: openWebResource
            };
        }());
        Dialog = (function () {
            var openAlertDialog, openConfirmDialog;
            openAlertDialog = function (parames) {
                Xrm.Dialog.openAlertDialog(parames.alertStrings, parames.options, parames.closeCallback);
            };
            openConfirmDialog = function (parames) {
                var confirmCallback = function () {
                    if (Core.Type.isFunction(parames.confirmCallback)) {
                        parames.confirmCallback();
                    }
                };
                var cancelCallback = function () {
                    if (Core.Type.isFunction(parames.cancelCallback)) {
                        parames.cancelCallback();
                    }
                };
                Xrm.Dialog.openConfirmDialog(parames.confirmDialogStrings, parames.dialogOptions, confirmCallback, cancelCallback);
            };
            return {
                openAlertDialog: openAlertDialog,
                openConfirmDialog: openConfirmDialog
            };
        }());
        Internal = (function () {
            var openLegacyWebDialog, openDialog;
            openLegacyWebDialog = function (parames) {
                Xrm.Internal.openLegacyWebDialog(parames.url, parames.options, parames.dialogArguments, parames.initFunctionName, parames.returnFunction);
            };
            openDialog = function (parames) {
                Xrm.Internal.openDialog(parames.url, parames.dialogOptions, parames.dialogArguments, parames.initFunctionName, parames.returnFunction);
            };
            return {
                openLegacyWebDialog: openLegacyWebDialog,
                openDialog: openDialog
            };
        }());
        WebApi = (function () {
            var createRecord, deleteRecord, updateRecord, retrieveRecord, retrieveMultipleRecords, execute, executeMultiple;
            createRecord = function (parames) {
                Xrm.WebApi.createRecord(parames.entityLogicalName, parames.data).then(parames.successCallback, parames.errorCallback);
            };
            deleteRecord = function (parames) {
                Xrm.WebApi.deleteRecord(parames.entityLogicalName, parames.id).then(parames.successCallback, parames.errorCallback);
            };
            updateRecord = function (parames) {
                Xrm.WebApi.updateRecord(parames.entityLogicalName, parames.id, parames.data).then(parames.successCallback, parames.errorCallback);
            };
            retrieveRecord = function (parames) {
                Xrm.WebApi.retrieveRecord(parames.entityLogicalName, parames.id, parames.options).then(parames.successCallback, parames.errorCallback);
            };
            retrieveMultipleRecords = function (parames) {
                Xrm.WebApi.retrieveMultipleRecords(parames.entityLogicalName, parames.options, parames.maxPageSize).then(parames.successCallback, parames.errorCallback);
            };
            execute = function (parmaes) {
                Xrm.WebApi.online.execute(parmaes.request).then(parmaes.successCallback, parmaes.errorCallback);
            };
            executeMultiple = function (parames) {
                Xrm.WebApi.online.executeMultiple(parames.requests).then(parames.successCallback, parames.errorCallback);
            };
            return {
                createRecord: createRecord,
                deleteRecord: deleteRecord,
                updateRecord: updateRecord,
                retrieveRecord: retrieveRecord,
                retrieveMultipleRecords: retrieveMultipleRecords,
                execute: execute,
                executeMultiple: executeMultiple
            };
        }());

        return {
            Base: Base,
            Utility: Utility,
            Navigation: Navigation,
            Dialog: Dialog,
            Internal: Internal,
            WebApi: WebApi
        };
    }());

    var Core = (function () {
        var Type, Ajax, Guid, Date;
        var Entity, Map, StringBuilder, ShareData;
        var Base;

        Base = (function () {
            var findFrameDynaHx = function () {

                for (var i = 0; i < window.top.frames.length; i++) {
                    try {
                        if (window.top.frames[i].DynaHx != null) {
                            return window.top.frames[i].DynaHx;
                        }
                    } catch (ex) {

                    }
                }
                return null;
            };
            return {
                findFrameDynaHx: findFrameDynaHx
            };
        }());
        Type = (function () {
            var isNull, isNullOrEmpty, isFunction, isBoolean, isArray, inArray, isNumber, isObject, isDate;
            isNull = function (o) {
                return o === undefined || o === null;
            };
            isNullOrEmpty = function (o) {
                return isNull(o) || (typeof o === "string" && !o.length);
            };
            isFunction = function (o) {
                return typeof o === "function";
            };
            isBoolean = function (o) {
                return typeof o === "boolean";
            };
            isArray = function (o) {
                return Array.isArray(o);
            };
            isNumber = function (o) {
                return typeof o === "number";
            };
            isObject = function (o) {
                return typeof o === "object";
            };
            isDate = function (o) {
                return o instanceof Date
            };
            inArray = function (elem, arr, i) {
                var len;
                var arrCore = [];
                if (arr) {
                    if (arrCore.indexOf) {
                        return arrCore.indexOf.call(arr, elem, i);
                    }
                    len = arr.length;
                    i = i ? i < 0 ? Math.max(0, len + i) : i : 0;
                    while (i < len) {
                        if (i in arr && arr[i] === elem) {
                            return i;
                        }
                        i++;
                    }
                }
                return -1;
            };
            return {
                isNull: isNull,
                isNullOrEmpty: isNullOrEmpty,
                isFunction: isFunction,
                isNumber: isNumber,
                isObject: isObject,
                isBoolean: isBoolean,
                isArray: isArray,
                inArray: inArray,
                isDate: isDate
            };
        }());
        Ajax = (function () {
            var createStandardXHR, createActiveXHR, createXHR, setHeader, send;
            createStandardXHR = function () {
                return new window.XMLHttpRequest();
            };
            createActiveXHR = function () {
                return new (window).ActiveXObject("Microsoft.XMLHTTP");
            };
            createXHR = function () {
                return window.ActiveXObject ? createActiveXHR() : createStandardXHR();
            };
            setHeader = function (xhr, headers) {
                if (Array.isArray(headers)) {
                    headers.forEach(function (item) {
                        xhr.setRequestHeader(item.name, item.value);
                    });
                }
            };
            send = function (parames) {
                var xhr = createXHR();
                if (parames.method == "GET" && !Type.isNull(parames.data)) {
                    Object.keys(parames.data).forEach(function (key, index) {
                        if (index == 0) {
                            parames.url += "?" + key + "=" + parames.data[key];
                        }
                        else {
                            parames.url += "&" + key + "=" + parames.data[key];
                        }
                    });
                    parames.data = null;
                }
                xhr.open(parames.method, parames.url, parames.async);
                setHeader(xhr, parames.headers);
                xhr.onreadystatechange = function () {
                    if (xhr.readyState == 4) {
                        xhr.onreadystatechange = null;
                        if (Type.isArray(parames.handles)) {
                            var isRun = false;
                            parames.handles.forEach(function (handle) {
                                if (Type.inArray(xhr.status, handle.multipleStates) >= 0) {
                                    if (Type.isFunction(handle.callback)) {
                                        handle.callback(xhr.response, xhr);
                                    }
                                    isRun = true;
                                    return;
                                }
                            });
                        }
                        if (!isRun) {
                            if (Type.isFunction(parames.otherCallback)) {
                                parames.otherCallback(xhr.response, xhr);
                            }
                        }


                        /* if (xhr.status == 200 || xhr.status == 204) {
                            if (Type.isFunction(parames.successCallback)) {
                                parames.successCallback(xhr.response, xhr);
                            }
                        } else {
                            if (Type.isFunction(parames.errCallback)) {
                                parames.errCallback(xhr.response, xhr);
                            }
                        } */
                    }
                };
                if (!Type.isNull(parames.data)) {
                    xhr.send(parames.data);
                }
                else {
                    xhr.send();
                }
            };
            return {
                send: send
            };
        }());
        Guid = (function () {
            var createGuid = function (value) {
                for (var $v_0 = "", $v_1 = 0; $v_1 < 8; $v_1++) $v_0 += Math.floor(Math.random() * 15).toString(15);
                $v_0 += "-";
                for (var $v_2 = 0; $v_2 < 4; $v_2++) $v_0 += Math.floor(Math.random() * 15).toString(15);
                $v_0 += "-";
                for (var $v_3 = 0; $v_3 < 4; $v_3++) $v_0 += Math.floor(Math.random() * 15).toString(15);
                $v_0 += "-";
                for (var $v_4 = 0; $v_4 < 4; $v_4++) $v_0 += Math.floor(Math.random() * 15).toString(15);
                $v_0 += "-";
                for (var $v_5 = 0; $v_5 < 12; $v_5++) $v_0 += Math.floor(Math.random() * 15).toString(15);
                return $v_0;
            }

            var _Guid = function () {
                this.value = "";
            };

            _Guid.prototype.toString = function (isBrackets) {
                isBrackets = Type.isBoolean(isBrackets) ? isBrackets : false;
                if (isBrackets) {
                    return "{" + this.value + "}";
                }
                else {
                    return this.value;
                }
            };

            _Guid.prototype.toLowerCase = function (isBrackets) {
                isBrackets = Type.isBoolean(isBrackets) ? isBrackets : false;
                if (isBrackets) {
                    return "{" + this.value.toLowerCase() + "}";
                }
                else {
                    return this.value.toLowerCase();
                }
            };

            _Guid.prototype.equals = function (o) {
                if (o.toString(true).toLowerCase() == this.toString(true).toLowerCase()) {
                    return true;
                }
                return false;
            }

            var newGuid = function () {
                var guid = new _Guid();
                guid.value = createGuid();
                return guid;
            };

            var parse = function (value) {
                value = value.toString().replace("{", "").replace("}", "");
                var reg = new RegExp(/^[0-9a-zA-Z]{8}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{12}$/);
                var guid = new _Guid();
                if (reg.test(value)) {
                    guid.value = value;
                }
                else {
                    throw new Error("guid无效");
                }
                return guid;
            };

            _Guid.newGuid = newGuid;
            _Guid.parse = parse;
            return _Guid;

        }());
        Entity = (function () {
            var _Entity = function (entityLogicalName, entityData) {
                if (!Type.isNullOrEmpty(entityLogicalName) && !Type.isNullOrEmpty(entityData)) {
                    this.entityLogicalName = entityLogicalName;
                    this.entityData = entityData;
                    this.id = null;
                    this.etag = null;
                    if (!Type.isNullOrEmpty(entityData[entityLogicalName + "id"])) {
                        this.id = Guid.parse(entityData[entityLogicalName + "id"]);
                    }
                    if (!Type.isNullOrEmpty(entityData["@odata.etag"])) {
                        this.etag = entityData["@odata.etag"];
                    }
                }
                else {
                    this.entityLogicalName = "";
                    this.entityData = {};
                }
            };


            _Entity.prototype.getInt = function (attrName) {
                if (Type.isNull(this.entityData[attrName])) {
                    return null;
                }
                return parseInt(this.entityData[attrName]);
            };

            _Entity.prototype.getFloat = function (attrName) {
                if (Type.isNull(this.entityData[attrName])) {
                    return null;
                }
                return parseFloat(this.entityData[attrName]);
            };

            _Entity.prototype.getBool = function (attrName) {
                if (Type.isNull(this.entityData[attrName])) {
                    return null;
                }
                if (!Type.isBoolean(this.entityData[attrName])) {
                    return null;
                }
                return this.entityData[attrName];
            };

            _Entity.prototype.getBoolFormat = function (attrName) {
                var val = this.entityData[attrName + "@OData.Community.Display.V1.FormattedValue"];
                if (Type.isNull(val)) {
                    return null;
                }
                return val;
            };

            _Entity.prototype.getDate = function (attrName) {
                if (Type.isNull(this.entityData[attrName])) {
                    return null;
                }
                if (this.entityData[attrName] == "") {
                    return null;
                }
                return new window.Date(this.entityData[attrName]);
            };

            _Entity.prototype.getDateFormat = function (attrName) {
                var val = this.entityData[attrName + "@OData.Community.Display.V1.FormattedValue"];
                if (Type.isNull(val)) {
                    return null;
                }
                return val;
            };

            _Entity.prototype.getOptionFormat = function (attrName) {
                var val = this.entityData[attrName + "@OData.Community.Display.V1.FormattedValue"];
                if (Type.isNull(val)) {
                    return null;
                }
                return val;
            };

            _Entity.prototype.getString = function (attrName) {
                if (Type.isNull(this.entityData[attrName])) {
                    return null;
                }
                return this.entityData[attrName].toString();
            };

            _Entity.prototype.getLookUpId = function (attrName) {
                var val = this.entityData["_" + attrName + "_value"];
                if (Type.isNull(val)) {
                    return null;
                }
                return val;
            };

            _Entity.prototype.getLookUpGuid = function (attrName) {
                var val = this.entityData["_" + attrName + "_value"];
                if (Type.isNull(val)) {
                    return null;
                }
                return Guid.parse(val);
            };

            _Entity.prototype.getLookUpName = function (attrName) {
                var val = this.entityData["_" + attrName + "_value@OData.Community.Display.V1.FormattedValue"];
                if (Type.isNull(val)) {
                    return null;
                }
                return val;
            };

            _Entity.prototype.getLookUpType = function (attrName) {
                var val = this.entityData["_" + attrName + "_value@Microsoft.Dynamics.CRM.lookuplogicalname"];
                if (Type.isNull(val)) {
                    return null;
                }
                return val;
            };

            _Entity.prototype.getLookUp = function (attrName) {
                var optionSet = {};
                optionSet["id"] = this.getLookUpId(attrName);
                optionSet["name"] = this.getLookUpName(attrName);
                optionSet["entityType"] = this.getLookUpType(attrName);
                if (Type.isNull(optionSet["id"]) || Type.isNull(optionSet["entityType"])) {
                    return null;
                }
                return optionSet;
            };

            _Entity.prototype.getMoneyFormat = function (attrName) {
                var val = this.entityData[attrName + "_base@OData.Community.Display.V1.FormattedValue"];
                if (Type.isNull(val)) {
                    return null;
                }
                return val;
            };

            _Entity.prototype.getEntity = function (attrName, entityName) {
                var val = this.entityData[attrName];
                if (Core.Type.isNullOrEmpty(entityName))
                    entityName = attrName;
                if (Type.isNull(val)) {
                    return null;
                }
                return new Entity(entityName, val);
            };

            _Entity.prototype.getEntities = function (attrName, entityName) {
                var val = this.entityData[attrName];
                if (Core.Type.isNullOrEmpty(entityName))
                    entityName = attrName;
                var entities = [];
                if (Type.isArray(val)) {
                    val.forEach(function (item) {
                        entities.push(new Entity(entityName, item));
                    });
                }
                return entities;
            };

            _Entity.prototype.getLinkLookUpId = function (attrName) {
                var val = this.entityData[attrName];
                if (Type.isNull(val)) {
                    return null;
                }
                return val;
            };

            _Entity.prototype.getLinkLookUpName = function (attrName) {
                var val = this.entityData[attrName + "@OData.Community.Display.V1.FormattedValue"];
                if (Type.isNull(val)) {
                    return null;
                }
                return val;
            };

            _Entity.prototype.getLinkLookUpType = function (attrName) {
                var val = this.entityData[attrName + "@Microsoft.Dynamics.CRM.lookuplogicalname"];
                if (Type.isNull(val)) {
                    return null;
                }
                return val;
            };

            _Entity.prototype.getLinkLookUp = function (attrName) {
                var optionSet = {};
                optionSet["id"] = this.getLinkLookUpId(attrName);
                optionSet["name"] = this.getLinkLookUpName(attrName);
                optionSet["entityType"] = this.getLinkLookUpType(attrName);
                if (Type.isNull(optionSet["id"]) || Type.isNull(optionSet["name"]) || Type.isNull(optionSet["entityType"])) {
                    return null;
                }
                return optionSet;
            };

            return _Entity;
        }());
        Map = (function () {
            var _Map = function () {
                this.keys = [];
                this.data = {};
            };
            _Map.prototype.add = function (key, val) {
                this.keys.push(key);
                this.data[key] = val;
            };
            _Map.prototype.has = function (key) {
                if (Type.inArray(key, this.keys) >= 0) {
                    return true;
                }
                return false;
            };
            _Map.prototype.getIndex = function (key) {
                return Type.inArray(key, this.keys);
            };
            _Map.prototype.set = function (key, val) {
                if (this.has(key)) {
                    this.data[key] = val;
                }
            };
            _Map.prototype.remove = function (key) {
                if (this.has(key)) {
                    this.keys.splice(this.getIndex(key), 1);
                    delete this.data[key];
                }
            };
            _Map.prototype.clear = function () {
                this.keys = [];
                this.data = {};
            };
            _Map.prototype.get = function (key) {
                if (this.has(key)) {
                    return this.data[key];
                }
                return null;
            };
            _Map.prototype.addJson = function (json) {
                Object.keys(json).forEach(function (key) {
                    this.add(key, json[key]);
                });

            };
            _Map.prototype.loadJson = function (json) {
                this.clear();
                this.addJson(json);
            };
            _Map.prototype.addArray = function (array, attrKey) {
                var that = this;
                array.forEach(function (value, index) {
                    if (!Core.Type.isNull(attrKey)) {
                        that.add(value[attrKey], value);
                    }
                    else {
                        that.add(index, value);
                    }
                });
            };
            _Map.prototype.loadArray = function (array, attrKey) {
                this.clear();
                this.addArray(array, attrKey);
            };
            _Map.prototype.insert = function (key, val, index) {
                this.keys.splice(index, 0, key);
                this.data[key] = val;
            };
            _Map.prototype.getLength = function () {
                return this.keys.length;
            };
            _Map.prototype.each = function (callback) {
                var index = 0;
                for (var key in this.data) {
                    index++;
                    callback(this.data[key], key, index);
                }
            };

            return _Map;
        }());
        StringBuilder = (function () {
            var _StringBuilder = function () {
                this.content = "";
            };
            _StringBuilder.prototype.append = function (formit, args) {
                if (Type.isArray(args) && args.length > 0) {
                    args.forEach(function (value, index) {
                        formit = formit.replace(new RegExp("\\{" + index + "\\}", "g"), value);
                    });
                }
                this.content += formit;
            };
            _StringBuilder.prototype.appendLine = function (formit, args) {
                this.append(formit + "\r\n", args);
            };
            _StringBuilder.prototype.toString = function () {
                return this.content;
            };
            return _StringBuilder;
        }());
        ShareData = (function () {

            var map = new Map();
            if (!Type.isNull(window.top.DynaHxMap)) {
                map = window.top.DynaHxMap;
            }
            else {
                window.top.DynaHxMap = map;
            }

            var set = function (key, value) {
                if (map.has(key)) {
                    map.set(key, value);
                }
                else {
                    map.add(key, value);
                }
            };
            var get = function (key) {
                if (map.has(key)) {
                    return map.get(key);
                }
                return null;
            }
            var remove = function (key) {
                if (map.has(key)) {
                    map.remove(key);
                }
            }
            var has = function (key) {
                return map.has(key);
            }
            var clear = function () {
                map.clear();
            }

            return {
                get: get,
                set: set,
                remove: remove,
                clear: clear,
                has: has
            }
        }());
        Date = (function () {
            //计算两个时间的月份
            var calcMonth = function (startdate, enddate) {

                var month = (enddate.getFullYear() - startdate.getFullYear()) * 12;
                month += enddate.getMonth() - startdate.getMonth();
                if (startdate.getDate() > enddate.getDate()) {
                    month -= 1;
                }
                return month;
            }
            //计算两个时间的天
            var calcDay = function (startdate, enddate) {
                var day = (enddate.getTime() - startdate.getTime()) / (1000 * 60 * 60 * 24);
                return parseInt(day);
            }
            //在当前日期上加上指定天
            var addDay = function (date, days) {
                date = +date + 1000 * 60 * 60 * 24 * days;
                date = new window.Date(date);
                return date;
            }
            //格式化日期
            var format = function (date, format) {
                date["M+"] = date.getMonth() + 1;
                date["d+"] = date.getDate();
                date["h+"] = date.getHours();
                date["m+"] = date.getMinutes();
                date["s+"] = date.getSeconds();
                date["q+"] = Math.floor((date.getMonth() + 3) / 3);
                date["S+"] = date.getMilliseconds();

                if (/(y+)/i.test(format)) {
                    format = format.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length));
                }

                for (var k in date) {
                    if (new RegExp("(" + k + ")").test(format)) {
                        format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? date[k] : ("00" + date[k]).substr(("" + date[k]).length));
                    }
                }
                return format;
            }
            return {
                calcMonth: calcMonth,
                calcDay: calcDay,
                addDay: addDay,
                format: format
            }
        }());

        return {
            Base: Base,
            ShareData: ShareData,
            Type: Type,
            Ajax: Ajax,
            Guid, Guid,
            Entity: Entity,
            Map: Map,
            StringBuilder: StringBuilder,
            Date: Date,
        };

    }());


    return {
        Grid: Grid,
        Fc: Fc,
        Da: Da,
        Log: Log,
        Bus: Bus,
        XrmEx: XrmEx,
        Core: Core,
    };
}());
